summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/kernel.pri4
-rw-r--r--src/gui/kernel/qapplication.cpp27
-rw-r--r--src/gui/kernel/qapplication_s60.cpp157
-rw-r--r--src/gui/kernel/qapplication_win.cpp9
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm27
-rw-r--r--src/gui/kernel/qcursor_s60.cpp24
-rw-r--r--src/gui/kernel/qdnd_s60.cpp4
-rw-r--r--src/gui/kernel/qevent.cpp122
-rw-r--r--src/gui/kernel/qevent.h2
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm23
-rw-r--r--src/gui/kernel/qgesture.cpp373
-rw-r--r--src/gui/kernel/qgesture.h19
-rw-r--r--src/gui/kernel/qgesturemanager.cpp18
-rw-r--r--src/gui/kernel/qgesturerecognizer.cpp137
-rw-r--r--src/gui/kernel/qgesturerecognizer.h2
-rw-r--r--src/gui/kernel/qmacgesturerecognizer_mac.mm267
-rw-r--r--src/gui/kernel/qmacgesturerecognizer_mac_p.h103
-rw-r--r--src/gui/kernel/qsoftkeymanager.cpp6
-rw-r--r--src/gui/kernel/qwidget.cpp33
-rw-r--r--src/gui/kernel/qwidget.h6
-rw-r--r--src/gui/kernel/qwidget_p.h3
-rw-r--r--src/gui/kernel/qwidget_s60.cpp78
22 files changed, 1243 insertions, 201 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 88c1f73..53c2611 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -205,6 +205,7 @@ embedded {
qcocoaview_mac_p.h \
qcocoaapplication_mac_p.h \
qcocoaapplicationdelegate_mac_p.h \
+ qmacgesturerecognizer_mac_p.h \
qmultitouch_mac_p.h
OBJECTIVE_SOURCES += \
@@ -224,7 +225,8 @@ embedded {
kernel/qdesktopwidget_mac.mm \
kernel/qeventdispatcher_mac.mm \
kernel/qcocoawindowcustomthemeframe_mac.mm \
- kernel/qmultitouch_mac.mm \
+ kernel/qmacgesturerecognizer_mac.mm \
+ kernel/qmultitouch_mac.mm
HEADERS += \
kernel/qt_cocoa_helpers_mac_p.h \
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index afc6f63..6f6d706 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -943,7 +943,7 @@ void QApplicationPrivate::initialize()
graphics_system = QGraphicsSystemFactory::create(graphics_system_name);
#endif
#ifndef QT_NO_WHEELEVENT
-#ifdef Q_OS_MAC
+#ifdef Q_OS_MAC
QApplicationPrivate::wheel_scroll_lines = 1;
#else
QApplicationPrivate::wheel_scroll_lines = 3;
@@ -1034,11 +1034,11 @@ QApplication::~QApplication()
d->eventDispatcher->closingDown();
d->eventDispatcher = 0;
+ QApplicationPrivate::is_app_closing = true;
+ QApplicationPrivate::is_app_running = false;
delete qt_desktopWidget;
qt_desktopWidget = 0;
- QApplicationPrivate::is_app_closing = true;
- QApplicationPrivate::is_app_running = false;
#ifndef QT_NO_CLIPBOARD
delete qt_clipboard;
@@ -5619,11 +5619,32 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window,
QApplicationPrivate::translateRawTouchEvent(window, deviceType, touchPoints);
}
+/*!
+ \since 4.6
+
+ Registers the given \a recognizer in the gesture framework and returns a gesture ID
+ for it.
+
+ The application takes ownership of the \a recognizer and returns the gesture type
+ ID associated with it. For gesture recognizers which handle custom QGesture
+ objects (i.e., those which return Qt::CustomGesture in a QGesture::gestureType()
+ function) the return value is a gesture ID between Qt::CustomGesture and
+ Qt::LastGestureType, inclusive.
+
+ \sa unregisterGestureRecognizer(), QGestureRecognizer::createGesture(), QGesture
+*/
Qt::GestureType QApplication::registerGestureRecognizer(QGestureRecognizer *recognizer)
{
return QGestureManager::instance()->registerGestureRecognizer(recognizer);
}
+/*!
+ \since 4.6
+
+ Unregisters all gesture recognizers of the specified \a type.
+
+ \sa registerGestureRecognizer()
+*/
void QApplication::unregisterGestureRecognizer(Qt::GestureType type)
{
QGestureManager::instance()->unregisterGestureRecognizer(type);
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index acd1041..cb9dda4 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -352,7 +352,8 @@ QSymbianControl::~QSymbianControl()
{
if (S60->curWin == this)
S60->curWin = 0;
- setFocusSafely(false);
+ if (!QApplicationPrivate::is_app_closing)
+ setFocusSafely(false);
S60->appUi()->RemoveFromStack(this);
delete m_longTapDetector;
}
@@ -463,12 +464,47 @@ void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent)
QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent));
}
+typedef QPair<QWidget*,QMouseEvent> Event;
+
+/*
+ * Helper function called by HandlePointerEvent - separated to keep that function readable
+ */
+static void generateEnterLeaveEvents(QList<Event> &events, QWidget *widgetUnderPointer,
+ QPoint globalPos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
+{
+ //moved to another widget, create enter and leave events
+ if (S60->lastPointerEventTarget) {
+ QMouseEvent mEventLeave(QEvent::Leave, S60->lastPointerEventTarget->mapFromGlobal(
+ S60->lastCursorPos), S60->lastCursorPos, button, QApplicationPrivate::mouse_buttons,
+ modifiers);
+ events.append(Event(S60->lastPointerEventTarget, mEventLeave));
+ }
+ if (widgetUnderPointer) {
+ QMouseEvent mEventEnter(QEvent::Enter, widgetUnderPointer->mapFromGlobal(globalPos),
+ globalPos, button, QApplicationPrivate::mouse_buttons, modifiers);
+
+ events.append(Event(widgetUnderPointer, mEventEnter));
+#ifndef QT_NO_CURSOR
+ S60->curWin = widgetUnderPointer->effectiveWinId();
+ if (!QApplication::overrideCursor()) {
+#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
+ if (S60->brokenPointerCursors)
+ qt_symbian_set_pointer_sprite(widgetUnderPointer->cursor());
+ else
+#endif
+ qt_symbian_setWindowCursor(widgetUnderPointer->cursor(), S60->curWin);
+ }
+#endif
+ }
+}
+
+
void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
{
- //### refactor me, getting too complex
QMouseEvent::Type type;
Qt::MouseButton button;
mapS60MouseEventTypeToQt(&type, &button, &pEvent);
+ Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers);
if (m_previousEventLongTap)
if (type == QEvent::MouseButtonRelease){
@@ -480,79 +516,76 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
return;
// store events for later sending/saving
- QWidget *alienWidget;
- typedef QPair<QWidget*,QMouseEvent> Event;
QList<Event > events;
QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY);
TPoint controlScreenPos = PositionRelativeToScreen();
QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos;
- if (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove)
- {
- // get the widget where the event happened
- alienWidget = qwidget->childAt(widgetPos);
- if (!alienWidget)
- alienWidget = qwidget;
- S60->mousePressTarget = alienWidget;
+ // widgets interested in the event
+ QWidget *widgetUnderPointer = qwidget->childAt(widgetPos);
+ if (!widgetUnderPointer)
+ widgetUnderPointer = qwidget; //i.e. this container widget
+
+ QWidget *widgetWithMouseGrab = QWidget::mouseGrabber();
+
+ // handle auto grab of pointer when pressing / releasing
+ if (!widgetWithMouseGrab && type == QEvent::MouseButtonPress) {
+ //if previously auto-grabbed, generate a fake mouse release (platform bug: mouse release event was lost)
+ if (S60->mousePressTarget) {
+ QMouseEvent mEvent(QEvent::MouseButtonRelease, S60->mousePressTarget->mapFromGlobal(globalPos), globalPos,
+ button, QApplicationPrivate::mouse_buttons, modifiers);
+ events.append(Event(S60->mousePressTarget,mEvent));
+ }
+ //auto grab the mouse
+ widgetWithMouseGrab = S60->mousePressTarget = widgetUnderPointer;
+ widgetWithMouseGrab->grabMouse();
+ }
+ if (widgetWithMouseGrab && widgetWithMouseGrab == S60->mousePressTarget && type == QEvent::MouseButtonRelease) {
+ //release the auto grab - note this release event still goes to the autograb widget
+ S60->mousePressTarget = 0;
+ widgetWithMouseGrab->releaseMouse();
}
- alienWidget = S60->mousePressTarget;
+ QWidget *widgetToReceiveMouseEvent;
+ if (widgetWithMouseGrab)
+ widgetToReceiveMouseEvent = widgetWithMouseGrab;
+ else
+ widgetToReceiveMouseEvent = widgetUnderPointer;
- if (alienWidget != S60->lastPointerEventTarget)
- if (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove)
- {
- //moved to another widget, create enter and leave events
- if (S60->lastPointerEventTarget)
- {
- QMouseEvent mEventLeave(QEvent::Leave, S60->lastPointerEventTarget->mapFromGlobal(S60->lastCursorPos), S60->lastCursorPos,
- button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers));
- events.append(Event(S60->lastPointerEventTarget,mEventLeave));
- }
- if (alienWidget) {
- QMouseEvent mEventEnter(QEvent::Enter, alienWidget->mapFromGlobal(globalPos),
- globalPos, button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(
- pEvent.iModifiers));
+ //queue QEvent::Enter and QEvent::Leave, if the pointer has moved
+ if (widgetUnderPointer != S60->lastPointerEventTarget && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove))
+ generateEnterLeaveEvents(events, widgetUnderPointer, globalPos, button, modifiers);
- events.append(Event(alienWidget, mEventEnter));
-#ifndef QT_NO_CURSOR
- S60->curWin = alienWidget->effectiveWinId();
- if (!QApplication::overrideCursor()) {
-#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
- if (S60->brokenPointerCursors)
- qt_symbian_set_pointer_sprite(alienWidget->cursor());
- else
-#endif
- qt_symbian_setWindowCursor(alienWidget->cursor(), S60->curWin);
- }
-#endif
- }
- }
+ //save global state
S60->lastCursorPos = globalPos;
+ S60->lastPointerEventPos = widgetPos;
+ S60->lastPointerEventTarget = widgetUnderPointer;
+
#if !defined(QT_NO_CURSOR) && !defined(Q_SYMBIAN_FIXED_POINTER_CURSORS)
if (S60->brokenPointerCursors)
qt_symbian_move_cursor_sprite();
#endif
- S60->lastPointerEventPos = widgetPos;
- S60->lastPointerEventTarget = alienWidget;
- if (alienWidget)
- {
- QMouseEvent mEvent(type, alienWidget->mapFromGlobal(globalPos), globalPos,
- button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers));
- events.append(Event(alienWidget,mEvent));
- QEventDispatcherS60 *dispatcher;
- // It is theoretically possible for someone to install a different event dispatcher.
- if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(alienWidget->d_func()->threadData->eventDispatcher)) != 0) {
- if (dispatcher->excludeUserInputEvents()) {
- for (int i=0;i < events.count();++i)
- {
- Event next = events[i];
- dispatcher->saveInputEvent(this, next.first, new QMouseEvent(next.second));
- }
- return;
+
+ //queue this event.
+ Q_ASSERT(widgetToReceiveMouseEvent);
+ QMouseEvent mEvent(type, widgetToReceiveMouseEvent->mapFromGlobal(globalPos), globalPos,
+ button, QApplicationPrivate::mouse_buttons, modifiers);
+ events.append(Event(widgetToReceiveMouseEvent,mEvent));
+ QEventDispatcherS60 *dispatcher;
+ // It is theoretically possible for someone to install a different event dispatcher.
+ if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widgetToReceiveMouseEvent->d_func()->threadData->eventDispatcher)) != 0) {
+ if (dispatcher->excludeUserInputEvents()) {
+ for (int i=0;i < events.count();++i)
+ {
+ Event next = events[i];
+ dispatcher->saveInputEvent(this, next.first, new QMouseEvent(next.second));
}
+ return;
}
}
+
+ //send events in the queue
for (int i=0;i < events.count();++i)
{
Event next = events[i];
@@ -688,7 +721,7 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod
Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
- false, 1, keyEvent.iScanCode, s60Keysym, mods);
+ false, 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
// WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
// if (!wid)
// Could happen if window isn't shown yet.
@@ -948,7 +981,8 @@ void QSymbianControl::setFocusSafely(bool focus)
S60->appUi()->RemoveFromStack(this);
QT_TRAP_THROWING(S60->appUi()->AddToStackL(this,
ECoeStackPriorityDefault, ECoeStackFlagStandard));
- lastFocusedControl = 0;
+ if(this == lastFocusedControl)
+ lastFocusedControl = 0;
this->SetFocus(false);
}
}
@@ -1121,6 +1155,11 @@ void qt_init(QApplicationPrivate * /* priv */, int)
;
}
*/
+
+ // Register WId with the metatype system. This is to enable
+ // QWidgetPrivate::create_sys to used delayed slot invokation in order
+ // to destroy WId objects during reparenting.
+ qRegisterMetaType<WId>("WId");
}
/*****************************************************************************
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 540f0a2..5bb25fa 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -819,13 +819,16 @@ void qt_init(QApplicationPrivate *priv, int)
priv->GetGestureInfo = 0;
priv->GetGestureExtraArgs = 0;
+ priv->CloseGestureInfoHandle = 0;
+ priv->SetGestureConfig = 0;
+ priv->GetGestureConfig = 0;
+ priv->BeginPanningFeedback = 0;
+ priv->UpdatePanningFeedback = 0;
+ priv->EndPanningFeedback = 0;
#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES)
priv->GetGestureInfo = (PtrGetGestureInfo) &TKGetGestureInfo;
priv->GetGestureExtraArgs = (PtrGetGestureExtraArgs) &TKGetGestureExtraArguments;
- priv->CloseGestureInfoHandle = (PtrCloseGestureInfoHandle) 0;
- priv->SetGestureConfig = (PtrSetGestureConfig) 0;
- priv->GetGestureConfig = (PtrGetGestureConfig) 0;
#elif !defined(Q_WS_WINCE)
priv->GetGestureInfo =
(PtrGetGestureInfo)QLibrary::resolve(QLatin1String("user32"),
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index b1c5fc5..4c2a14a 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -1066,7 +1066,10 @@ extern "C" {
sendToPopup = true;
}
- if (widgetToGetKey->testAttribute(Qt::WA_InputMethodEnabled)) {
+ if (widgetToGetKey->testAttribute(Qt::WA_InputMethodEnabled)
+ && !(widgetToGetKey->inputMethodHints() & Qt::ImhDigitsOnly
+ || widgetToGetKey->inputMethodHints() & Qt::ImhFormattedNumbersOnly
+ || widgetToGetKey->inputMethodHints() & Qt::ImhHiddenText)) {
[qt_mac_nativeview_for(widgetToGetKey) interpretKeyEvents:[NSArray arrayWithObject: theEvent]];
}
if (sendKeyEvents && !composing) {
@@ -1420,29 +1423,29 @@ Qt::DropAction QDragManager::drag(QDrag *o)
// convert the image to NSImage.
NSImage *image = (NSImage *)qt_mac_create_nsimage(pix);
[image retain];
- DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent];
+ DnDParams dndParams = *[QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent];
// save supported actions
- [dndParams->view setSupportedActions: qt_mac_mapDropActions(dragPrivate()->possible_actions)];
- NSPoint imageLoc = {dndParams->localPoint.x - hotspot.x(),
- dndParams->localPoint.y + pix.height() - hotspot.y()};
+ [dndParams.view setSupportedActions: qt_mac_mapDropActions(dragPrivate()->possible_actions)];
+ NSPoint imageLoc = {dndParams.localPoint.x - hotspot.x(),
+ dndParams.localPoint.y + pix.height() - hotspot.y()};
NSSize mouseOffset = {0.0, 0.0};
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
- NSPoint windowPoint = [dndParams->theEvent locationInWindow];
+ NSPoint windowPoint = [dndParams.theEvent locationInWindow];
dragPrivate()->executed_action = Qt::ActionMask;
// do the drag
- [dndParams->view retain];
- [dndParams->view dragImage:image
+ [dndParams.view retain];
+ [dndParams.view dragImage:image
at:imageLoc
offset:mouseOffset
- event:dndParams->theEvent
+ event:dndParams.theEvent
pasteboard:pboard
- source:dndParams->view
+ source:dndParams.view
slideBack:YES];
- [dndParams->view release];
+ [dndParams.view release];
[image release];
dragPrivate()->executed_action = Qt::IgnoreAction;
object = 0;
- Qt::DropAction performedAction(qt_mac_mapNSDragOperation(dndParams->performedAction));
+ Qt::DropAction performedAction(qt_mac_mapNSDragOperation(dndParams.performedAction));
// do post drag processing, if required.
if(performedAction != Qt::IgnoreAction) {
// check if the receiver points us to a file location.
diff --git a/src/gui/kernel/qcursor_s60.cpp b/src/gui/kernel/qcursor_s60.cpp
index 0d8283d..7f5c32a 100644
--- a/src/gui/kernel/qcursor_s60.cpp
+++ b/src/gui/kernel/qcursor_s60.cpp
@@ -110,7 +110,7 @@ void qt_symbian_set_cursor_visible(bool visible) {
else
cursorSpriteVisible--;
Q_ASSERT(cursorSpriteVisible >=0);
-
+
if (cursorSpriteVisible && !S60->mouseInteractionEnabled) {
#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
if (S60->brokenPointerCursors)
@@ -119,7 +119,7 @@ void qt_symbian_set_cursor_visible(bool visible) {
#endif
S60->wsSession().SetPointerCursorMode(EPointerCursorNormal);
} else if (!cursorSpriteVisible && S60->mouseInteractionEnabled) {
-#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
+#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
if (S60->brokenPointerCursors)
qt_symbian_hide_pointer_sprite();
else
@@ -188,7 +188,7 @@ Qt::HANDLE QCursor::handle() const
return reinterpret_cast<Qt::HANDLE> (&(d->pcurs));
#ifdef Q_SYMBIAN_HAS_SYSTEM_CURSORS
- // don't construct shape cursors, QApplication_s60 will use the system cursor instead
+ // don't construct shape cursors, QApplication_s60 will use the system cursor instead
if (!(d->bm))
return 0;
#endif
@@ -228,12 +228,12 @@ void QCursorData::loadShapeFromResource(RWsSpriteBase& target, QString resource,
/*
* Constructs the native cursor from resources compiled into QtGui
* This is needed only when the platform doesn't have system cursors.
- *
+ *
* System cursors are higher performance, since they are constructed once
* and shared by all applications by specifying the shape number.
* Due to symbian platform security considerations, and the fact most
* existing phones have a broken RWsPointerCursor, system cursors are not
- * being used.
+ * being used.
*/
void QCursorData::constructShapeSprite(RWsSpriteBase& target)
{
@@ -346,7 +346,7 @@ void QCursorData::constructCursorSprite(RWsSpriteBase& target)
member->iMaskBitmap = pixmap.mask().toSymbianCFbsBitmap();
}
else {
- member->iMaskBitmap = pixmap.createHeuristicMask().toSymbianCFbsBitmap();
+ member->iMaskBitmap = 0; //opaque rectangle cursor (due to EDrawModePEN)
}
}
@@ -371,11 +371,11 @@ void qt_symbian_show_pointer_sprite()
} else {
cursorSprite = QCursor(Qt::ArrowCursor);
}
-
+
cursorSprite.d->scurs = RWsSprite(S60->wsSession());
QPoint pos = QCursor::pos();
cursorSprite.d->scurs.Construct(S60->windowGroup(), TPoint(pos.x(), pos.y()), ESpriteNoChildClip | ESpriteNoShadows);
-
+
cursorSprite.d->constructCursorSprite(cursorSprite.d->scurs);
cursorSprite.d->scurs.Activate();
}
@@ -409,7 +409,7 @@ void qt_symbian_set_pointer_sprite(const QCursor& cursor)
* RWsPointerCursor, this function is called in response to pointer events
* and when QCursor::setPos() is called.
* Performance is worse than a real pointer cursor, due to extra context
- * switches vs. the window server moving the cursor by itself.
+ * switches vs. the window server moving the cursor by itself.
*/
void qt_symbian_move_cursor_sprite()
{
@@ -421,7 +421,7 @@ void qt_symbian_move_cursor_sprite()
/*
* Translate from Qt::CursorShape to OS system pointer cursor list index.
* Currently we control the implementation of the system pointer cursor list,
- * so this function is trivial. That may not always be the case.
+ * so this function is trivial. That may not always be the case.
*/
TInt qt_symbian_translate_cursor_shape(Qt::CursorShape shape)
{
@@ -462,7 +462,7 @@ void qt_symbian_set_cursor(QWidget *w, bool force)
/*
* Makes the specified cursor appear above a specific native window group
* Called from QSymbianControl and QApplication::restoreOverrideCursor
- *
+ *
* Window server is needed for this, so there is no equivalent when using
* the sprite workaround.
*/
@@ -486,7 +486,7 @@ void qt_symbian_setWindowGroupCursor(const QCursor &cursor, RWindowTreeNode &nod
/*
* Makes the specified cursor appear above a specific native window
* Called from QSymbianControl and QApplication::restoreOverrideCursor
- *
+ *
* Window server is needed for this, so there is no equivalent when using
* the sprite workaround.
*/
diff --git a/src/gui/kernel/qdnd_s60.cpp b/src/gui/kernel/qdnd_s60.cpp
index 3d6ecd2..a8d3ac5 100644
--- a/src/gui/kernel/qdnd_s60.cpp
+++ b/src/gui/kernel/qdnd_s60.cpp
@@ -277,7 +277,7 @@ Qt::DropAction QDragManager::drag(QDrag *o)
qApp->installEventFilter(this);
- global_accepted_action = Qt::MoveAction;
+ global_accepted_action = defaultAction(dragPrivate()->possible_actions, Qt::NoModifier);
qt_symbian_dnd_dragging = true;
eventLoop = new QEventLoop;
@@ -288,7 +288,7 @@ Qt::DropAction QDragManager::drag(QDrag *o)
#ifndef QT_NO_CURSOR
qt_symbian_set_cursor_visible(false);
-
+
overrideCursor = QCursor(); //deref the cursor data
qt_symbian_dnd_dragging = false;
#endif
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 4316714..2ff6d65 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3563,6 +3563,7 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar)
\brief The QTouchEvent class contains parameters that describe a touch event.
\since 4.6
\ingroup events
+ \ingroup multitouch
\section1 Enabling Touch Events
@@ -4195,32 +4196,49 @@ QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::T
\class QGestureEvent
\since 4.6
\ingroup events
+ \ingroup gestures
- \brief The QGestureEvent class provides the description of triggered
- gestures.
+ \brief The QGestureEvent class provides the description of triggered gestures.
- The QGestureEvent class contains a list of gestures that are being executed
- right now (\l{QGestureEvent::}{activeGestures()}) and a list of gestures
- that are \l{QGestureEvent::canceledGestures}{cancelled} (a gesture might be
- cancelled because the window lost focus, or because of timeout, etc).
+ The QGestureEvent class contains a list of gestures, which can be obtained using the
+ allGestures() function.
- \sa QGesture
+ The gestures are either active or canceled. A list of those that are currently being
+ executed can be obtained using the activeGestures() function. A list of those which
+ were previously active and have been canceled can be accessed using the
+ canceledGestures() function. A gesture might be canceled if the current window loses
+ focus, for example, or because of a timeout, or for other reasons.
+
+ If the event handler does not accept the event by calling the generic
+ QEvent::accept() function, all individual QGesture object that were not accepted
+ will be propagated up the parent widget chain until a widget accepts them
+ individually, by calling QGestureEvent::accept() for each of them, or an event
+ filter consumes the event.
+
+ \sa QGesture, QGestureRecognizer,
+ QWidget::grabGesture(), QGraphicsObject::grabGesture()
*/
/*!
Creates new QGestureEvent containing a list of \a gestures.
*/
-QGestureEvent::QGestureEvent(const QList<QGesture*> &gestures)
+QGestureEvent::QGestureEvent(const QList<QGesture *> &gestures)
: QEvent(QEvent::Gesture), gestures_(gestures)
{
}
-QList<QGesture*> QGestureEvent::allGestures() const
+/*!
+ Returns all gestures that are delivered in the event.
+*/
+QList<QGesture *> QGestureEvent::allGestures() const
{
return gestures_;
}
-QGesture* QGestureEvent::gesture(Qt::GestureType type)
+/*!
+ Returns a gesture object by \a type.
+*/
+QGesture *QGestureEvent::gesture(Qt::GestureType type) const
{
for(int i = 0; i < gestures_.size(); ++i)
if (gestures_.at(i)->gestureType() == type)
@@ -4228,16 +4246,35 @@ QGesture* QGestureEvent::gesture(Qt::GestureType type)
return 0;
}
-QList<QGesture*> QGestureEvent::activeGestures() const
+/*!
+ Returns a list of active (not canceled) gestures.
+*/
+QList<QGesture *> QGestureEvent::activeGestures() const
{
return gestures_;
}
-QList<QGesture*> QGestureEvent::canceledGestures() const
+/*!
+ Returns a list of canceled gestures.
+*/
+QList<QGesture *> QGestureEvent::canceledGestures() const
{
return gestures_;
}
+/*!
+ Sets the accept flag of the given \a gesture object to the specified \a value.
+
+ Setting the accept flag indicates that the event receiver wants the \a gesture.
+ Unwanted gestures may be propagated to the parent widget.
+
+ By default, gestures in events of type QEvent::Gesture are accepted, and
+ gestures in QEvent::GestureOverride events are ignored.
+
+ For convenience, the accept flag can also be set with
+ \l{QGestureEvent::accept()}{accept(gesture)}, and cleared with
+ \l{QGestureEvent::ignore()}{ignore(gesture)}.
+*/
void QGestureEvent::setAccepted(QGesture *gesture, bool value)
{
setAccepted(false);
@@ -4245,19 +4282,80 @@ void QGestureEvent::setAccepted(QGesture *gesture, bool value)
gesture->d_func()->accept = value;
}
+/*!
+ Sets the accept flag of the given \a gesture object, the equivalent of calling
+ \l{QGestureEvent::setAccepted()}{setAccepted(gesture, true)}.
+
+ Setting the accept flag indicates that the event receiver wants the
+ gesture. Unwanted gestures may be propagated to the parent widget.
+
+ \sa QGestureEvent::ignore()
+*/
void QGestureEvent::accept(QGesture *gesture)
{
setAccepted(gesture, true);
}
+/*!
+ Clears the accept flag parameter of the given \a gesture object, the equivalent
+ of calling \l{QGestureEvent::setAccepted()}{setAccepted(gesture, false)}.
+
+ Clearing the accept flag indicates that the event receiver does not
+ want the gesture. Unwanted gestures may be propgated to the parent widget.
+
+ \sa QGestureEvent::accept()
+*/
void QGestureEvent::ignore(QGesture *gesture)
{
setAccepted(gesture, false);
}
+/*!
+ Returns true if the \a gesture is accepted; otherwise returns false.
+*/
bool QGestureEvent::isAccepted(QGesture *gesture) const
{
return gesture ? gesture->d_func()->accept : false;
}
+#ifdef Q_NO_USING_KEYWORD
+/*!
+ \fn void QGestureEvent::setAccepted(bool accepted)
+
+ Sets or clears the event's internal flag that determines whether it should
+ be delivered to other objects.
+
+ Calling this function with a value of true for \a accepted indicates that the
+ caller has accepted the event and that it should not be propagated further.
+ Calling this function with a value of false indicates that the caller has
+ ignored the event and that it should be delivered to other objects.
+
+ For convenience, the accept flag can also be set with accept(), and cleared
+ with ignore().
+
+ \sa QEvent::accepted
+*/
+/*!
+ \fn bool QGestureEvent::isAccepted() const
+
+ Returns true is the event has been accepted; otherwise returns false.
+
+ \sa QEvent::accepted
+*/
+/*!
+ \fn void QGestureEvent::accept()
+
+ Accepts the event, the equivalent of calling setAccepted(true).
+
+ \sa QEvent::accept()
+*/
+/*!
+ \fn void QGestureEvent::ignore()
+
+ Ignores the event, the equivalent of calling setAccepted(false).
+
+ \sa QEvent::ignore()
+*/
+#endif
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 224b479..3516222 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -826,7 +826,7 @@ public:
QGestureEvent(const QList<QGesture *> &gestures);
QList<QGesture *> allGestures() const;
- QGesture *gesture(Qt::GestureType type);
+ QGesture *gesture(Qt::GestureType type) const;
QList<QGesture *> activeGestures() const;
QList<QGesture *> canceledGestures() const;
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
index 7152705..c9dd949 100644
--- a/src/gui/kernel/qeventdispatcher_mac.mm
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -136,14 +136,19 @@ void QEventDispatcherMacPrivate::activateTimer(CFRunLoopTimerRef, void *info)
if (tmr == 0 || tmr->pending == true)
return; // Can't send another timer event if it's pending.
- tmr->pending = true;
- QTimerEvent e(tmr->id);
- qt_sendSpontaneousEvent(tmr->obj, &e);
- // Get the value again in case the timer gets unregistered during the sendEvent.
- tmr = macTimerHash.value(timerID);
- if (tmr != 0)
- tmr->pending = false;
+ if (blockSendPostedEvents) {
+ QCoreApplication::postEvent(tmr->obj, new QTimerEvent(tmr->id));
+ } else {
+ tmr->pending = true;
+ QTimerEvent e(tmr->id);
+ qt_sendSpontaneousEvent(tmr->obj, &e);
+ // Get the value again in case the timer gets unregistered during the sendEvent.
+ tmr = macTimerHash.value(timerID);
+ if (tmr != 0)
+ tmr->pending = false;
+ }
+
}
void QEventDispatcherMac::registerTimer(int timerId, int interval, QObject *obj)
@@ -767,7 +772,7 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession()
// Sadly, we need to introduce this little event flush
// to stop dialogs from blinking/poping in front if a
// modal session restart was needed:
- while (NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ while (NSEvent *event = [NSApp nextEventMatchingMask:0
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue: YES]) {
@@ -942,7 +947,7 @@ Boolean QEventDispatcherMacPrivate::postedEventSourceEqualCallback(const void *i
inline static void processPostedEvents(QEventDispatcherMacPrivate *const d, const bool blockSendPostedEvents)
{
- if (blockSendPostedEvents) {
+ if (blockSendPostedEvents || d->interrupt) {
CFRunLoopSourceSignal(d->postedEventsSource);
} else {
if (!d->threadData->canWait || (d->serialNumber != d->lastSerial)) {
diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp
index bb74aec..fc8df49 100644
--- a/src/gui/kernel/qgesture.cpp
+++ b/src/gui/kernel/qgesture.cpp
@@ -47,46 +47,103 @@ QT_BEGIN_NAMESPACE
/*!
\class QGesture
\since 4.6
+ \ingroup gestures
- \brief The QGesture class represents a gesture, containing all
- properties that describe a gesture.
+ \brief The QGesture class represents a gesture, containing properties that
+ describe the corresponding user input.
- The widget receives a QGestureEvent with a list of QGesture
- objects that represent gestures that are occuring on it. The class
- has a list of properties that can be queried by the user to get
- some gesture-specific arguments (i.e. position of the tap in the
- DoubleTap gesture).
+ Gesture objects are not constructed directly by developers. They are created by
+ the QGestureRecognizer object that is registered with the application; see
+ QApplication::registerGestureRecognizer().
- 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.
+ \section1 Gesture Properties
+
+ The class has a list of properties that can be queried by the user to get
+ some gesture-specific arguments. For example, the pinch gesture has a scale
+ factor that is exposed as a property.
+
+ Developers of custom gesture recognizers can add additional properties in
+ order to provide additional information about a gesture. This can be done
+ by adding new dynamic properties to a QGesture object, or by subclassing
+ the QGesture class (or one of its subclasses).
+
+ \section1 Lifecycle of a Gesture Object
+
+ A QGesture instance is created when the application calls QWidget::grabGesture()
+ or QGraphicsObject::grabGesture() to configure a widget or graphics object (the
+ target object) for gesture input. One gesture object is created for each target
+ object.
+
+ The registered gesture recognizer monitors the input events for the target
+ object via its \l{QGestureRecognizer::}{filterEvent()} function, updating the
+ properties of the gesture object as required.
+
+ The gesture object may be delivered to the target object in a QGestureEvent if
+ the corresponding gesture is active or has just been canceled. Each event that
+ is delivered contains a list of gesture objects, since support for more than
+ one gesture may be enabled for the target object. Due to the way events are
+ handled in Qt, gesture events may be filtered by other objects.
\sa QGestureEvent, QGestureRecognizer
*/
-QGesture::QGesture(Qt::GestureType type, QObject *parent)
- : QObject(*new QGesturePrivate, parent)
-{
- d_func()->gestureType = type;
-}
+/*!
+ Constructs a new gesture object with the given \a parent.
+ QGesture objects are created by gesture recognizers in the
+ QGestureRecognizer::createGesture() function.
+*/
QGesture::QGesture(QObject *parent)
: QObject(*new QGesturePrivate, parent)
{
d_func()->gestureType = Qt::CustomGesture;
}
-QGesture::QGesture(QGesturePrivate &dd, Qt::GestureType type, QObject *parent)
+/*!
+ \internal
+*/
+QGesture::QGesture(QGesturePrivate &dd, QObject *parent)
: QObject(dd, parent)
{
- d_func()->gestureType = type;
}
+/*!
+ Destroys the gesture object.
+*/
QGesture::~QGesture()
{
}
+/*!
+ \property QGesture::state
+ \brief the current state of the gesture
+*/
+
+/*!
+ \property QGesture::gestureType
+ \brief the type of the gesture
+*/
+
+/*!
+ \property QGesture::hotSpot
+
+ \brief The point that is used to find the receiver for the gesture event.
+
+ If the hot-spot is not set, the targetObject is used as the receiver of the
+ gesture event.
+*/
+
+/*!
+ \property QGesture::hasHotSpot
+ \brief whether the gesture has a hot-spot
+*/
+
+/*!
+ \property QGesture::targetObject
+ \brief the target object which will receive the gesture event if the hotSpot is
+ not set
+*/
+
Qt::GestureType QGesture::gestureType() const
{
return d_func()->gestureType;
@@ -97,7 +154,7 @@ Qt::GestureState QGesture::state() const
return d_func()->state;
}
-QObject* QGesture::targetObject() const
+QObject *QGesture::targetObject() const
{
return d_func()->targetObject;
}
@@ -129,12 +186,59 @@ void QGesture::unsetHotSpot()
d_func()->isHotSpotSet = false;
}
-// QPanGesture
+/*!
+ \class QPanGesture
+ \since 4.6
+ \brief The QPanGesture class describes a panning gesture made by the user.
+ \ingroup gestures
+
+ \image pangesture.png
+
+ \sa {Gestures Programming}, QPinchGesture, QSwipeGesture
+*/
+
+/*!
+ \property QPanGesture::totalOffset
+ \brief the total offset from the first input position to the current input
+ position
+ The total offset measures the total change in position of the user's input
+ covered by the gesture on the input device.
+*/
+
+/*!
+ \property QPanGesture::lastOffset
+ \brief the last offset recorded for this gesture
+
+ The last offset contains the change in position of the user's input as
+ reported in the \l offset property when a previous gesture event was
+ delivered for this gesture.
+
+ If no previous event was delivered with information about this gesture
+ (i.e., this gesture object contains information about the first movement
+ in the gesture) then this property contains a zero size.
+*/
+
+/*!
+ \property QPanGesture::offset
+ \brief the offset from the previous input position to the current input
+ position
+
+ The offset measures the change in position of the user's input on the
+ input device.
+*/
+
+/*!
+ \property QPanGesture::acceleration
+*/
+
+/*!
+ \internal
+*/
QPanGesture::QPanGesture(QObject *parent)
- : QGesture(*new QPanGesturePrivate, Qt::PanGesture, parent)
+ : QGesture(*new QPanGesturePrivate, parent)
{
-
+ d_func()->gestureType = Qt::PanGesture;
}
QSizeF QPanGesture::totalOffset() const
@@ -178,12 +282,143 @@ void QPanGesture::setAcceleration(qreal value)
d_func()->acceleration = value;
}
-// QPinchGesture
+/*!
+ \class QPinchGesture
+ \since 4.6
+ \brief The QPinchGesture class describes a pinch gesture made my the user.
+ \ingroup multitouch
+ \ingroup gestures
+
+ A pinch gesture is a form of multitouch user input in which the user typically
+ touches two points on the input device with a thumb and finger, before moving
+ them closer together or further apart to change the scale factor, zoom, or level
+ of detail of the user interface.
+
+ \image pinchgesture.png
+
+ Instead of repeatedly applying the same pinching gesture, the user may
+ continue to touch the input device in one place, and apply a second touch
+ to a new point, continuing the gesture. When this occurs, gesture events
+ will continue to be delivered to the target object, containing an instance
+ of QPinchGesture in the Qt::GestureUpdated state.
+
+ \sa {Gestures Programming}, QPanGesture, QSwipeGesture
+*/
+
+/*!
+ \enum QPinchGesture::WhatChange
+
+ This enum describes the changes that can occur to the properties of
+ the gesture object.
+
+ \value ScaleFactorChanged The scale factor held by scaleFactor changed.
+ \value RotationAngleChanged The rotation angle held by rotationAngle changed.
+ \value CenterPointChanged The center point held by centerPoint changed.
+
+ \sa whatChanged
+*/
+
+/*!
+ \property QPinchGesture::whatChanged
+ \brief the property of the gesture that has changed
+
+ This property indicates which of the other properties has changed since
+ the previous gesture event included information about this gesture. You
+ can use this information to determine which aspect of your user interface
+ needs to be updated.
+
+ \sa scaleFactor, rotationAngle, centerPoint
+*/
+
+/*!
+ \property QPinchGesture::totalScaleFactor
+ \brief the total scale factor
+ The total scale factor measures the total change in scale factor from the
+ original value to the current scale factor.
+
+ \sa scaleFactor, lastScaleFactor
+*/
+/*!
+ \property QPinchGesture::lastScaleFactor
+ \brief the last scale factor recorded for this gesture
+
+ The last scale factor contains the scale factor reported in the
+ \l scaleFactor property when a previous gesture event included
+ information about this gesture.
+
+ If no previous event was delivered with information about this gesture
+ (i.e., this gesture object contains information about the first movement
+ in the gesture) then this property contains zero.
+
+ \sa scaleFactor, totalScaleFactor
+*/
+/*!
+ \property QPinchGesture::scaleFactor
+ \brief the current scale factor
+
+ The scale factor measures the scale factor associated with the distance
+ between two of the user's inputs on a multitouch device.
+
+ \sa totalScaleFactor, lastScaleFactor
+*/
+
+/*!
+ \property QPinchGesture::totalRotationAngle
+ \brief the total angle covered by the gesture
+
+ This total angle measures the complete angle covered by the gesture. Usually, this
+ is equal to the value held by the \l rotationAngle property, except in the case where
+ the user performs multiple rotations by removing and repositioning one of the touch
+ points, as described above. In this case, the total angle will be the sum of the
+ rotation angles for the multiple stages of the gesture.
+
+ \sa rotationAngle, lastRotationAngle
+*/
+/*!
+ \property QPinchGesture::lastRotationAngle
+ \brief the last reported angle covered by the gesture motion
+
+ The last rotation angle is the angle as reported in the \l rotationAngle property
+ when a previous gesture event was delivered for this gesture.
+
+ \sa rotationAngle, totalRotationAngle
+*/
+/*!
+ \property QPinchGesture::rotationAngle
+ \brief the angle covered by the gesture motion
+
+ \sa totalRotationAngle, lastRotationAngle
+*/
+
+/*!
+ \property QPinchGesture::startCenterPoint
+ \brief the starting position of the center point
+
+ \sa centerPoint, lastCenterPoint
+*/
+/*!
+ \property QPinchGesture::lastCenterPoint
+ \brief the last position of the center point recorded for this gesture
+
+ \sa centerPoint, startCenterPoint
+*/
+/*!
+ \property QPinchGesture::centerPoint
+ \brief the current center point
+
+ The center point is the midpoint between the two input points in the gesture.
+
+ \sa startCenterPoint, lastCenterPoint
+*/
+
+/*!
+ \internal
+*/
QPinchGesture::QPinchGesture(QObject *parent)
- : QGesture(*new QPinchGesturePrivate, Qt::PinchGesture, parent)
+ : QGesture(*new QPinchGesturePrivate, parent)
{
-
+ d_func()->gestureType = Qt::PinchGesture;
}
QPinchGesture::WhatChanged QPinchGesture::whatChanged() const
@@ -289,31 +524,91 @@ void QPinchGesture::setRotationAngle(qreal value)
d_func()->rotationAngle = value;
}
-// QSwipeGesture
+/*!
+ \class QSwipeGesture
+ \since 4.6
+ \brief The QSwipeGesture class describes a swipe gesture made by the user.
+ \ingroup gestures
+
+ \image swipegesture.png
+
+ \sa {Gestures Programming}, QPanGesture, QPinchGesture
+*/
+
+/*!
+ \enum QSwipeGesture::SwipeDirection
+
+ This enum describes the possible directions for the gesture's motion
+ along the horizontal and vertical axes.
+
+ \value NoDirection The gesture had no motion associated with it on a particular axis.
+ \value Left The gesture involved a horizontal motion to the left.
+ \value Right The gesture involved a horizontal motion to the right.
+ \value Up The gesture involved an upward vertical motion.
+ \value Down The gesture involved a downward vertical motion.
+*/
+
+/*!
+ \property QSwipeGesture::horizontalDirection
+ \brief the horizontal direction of the gesture
+
+ If the gesture has a horizontal component, the horizontal direction
+ is either Left or Right; otherwise, it is NoDirection.
+
+ \sa verticalDirection, swipeAngle
+*/
+
+/*!
+ \property QSwipeGesture::verticalDirection
+ \brief the vertical direction of the gesture
+ If the gesture has a vertical component, the vertical direction
+ is either Up or Down; otherwise, it is NoDirection.
+
+ \sa horizontalDirection, swipeAngle
+*/
+
+/*!
+ \property QSwipeGesture::swipeAngle
+ \brief the angle of the motion associated with the gesture
+
+ If the gesture has either a horizontal or vertical component, the
+ swipe angle describes the angle between the direction of motion and the
+ x-axis as defined using the standard widget
+ \l{The Coordinate System}{coordinate system}.
+
+ \sa horizontalDirection, verticalDirection
+*/
+
+/*!
+ \internal
+*/
QSwipeGesture::QSwipeGesture(QObject *parent)
- : QGesture(*new QSwipeGesturePrivate, Qt::SwipeGesture, parent)
+ : QGesture(*new QSwipeGesturePrivate, parent)
{
+ d_func()->gestureType = Qt::SwipeGesture;
}
QSwipeGesture::SwipeDirection QSwipeGesture::horizontalDirection() const
{
- return d_func()->horizontalDirection;
+ Q_D(const QSwipeGesture);
+ if (d->swipeAngle < 0 || d->swipeAngle == 90 || d->swipeAngle == 270)
+ return QSwipeGesture::NoDirection;
+ else if (d->swipeAngle < 90 || d->swipeAngle > 270)
+ return QSwipeGesture::Right;
+ else
+ return QSwipeGesture::Left;
}
QSwipeGesture::SwipeDirection QSwipeGesture::verticalDirection() const
{
- return d_func()->verticalDirection;
-}
-
-void QSwipeGesture::setHorizontalDirection(QSwipeGesture::SwipeDirection value)
-{
- d_func()->horizontalDirection = value;
-}
-
-void QSwipeGesture::setVerticalDirection(QSwipeGesture::SwipeDirection value)
-{
- d_func()->verticalDirection = value;
+ Q_D(const QSwipeGesture);
+ if (d->swipeAngle <= 0 || d->swipeAngle == 180)
+ return QSwipeGesture::NoDirection;
+ else if (d->swipeAngle < 180)
+ return QSwipeGesture::Up;
+ else
+ return QSwipeGesture::Down;
}
qreal QSwipeGesture::swipeAngle() const
diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h
index b37120f..02eb526 100644
--- a/src/gui/kernel/qgesture.h
+++ b/src/gui/kernel/qgesture.h
@@ -51,12 +51,12 @@
QT_BEGIN_HEADER
+Q_DECLARE_METATYPE(Qt::GestureState)
+
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-Q_DECLARE_METATYPE(Qt::GestureState)
-
class QGesturePrivate;
class Q_GUI_EXPORT QGesture : public QObject
{
@@ -70,8 +70,7 @@ class Q_GUI_EXPORT QGesture : public QObject
Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject)
public:
- explicit QGesture(Qt::GestureType type = Qt::CustomGesture, QObject *parent = 0);
- explicit QGesture(QObject *parent);
+ explicit QGesture(QObject *parent = 0);
~QGesture();
Qt::GestureType gestureType() const;
@@ -87,7 +86,7 @@ public:
void unsetHotSpot();
protected:
- QGesture(QGesturePrivate &dd, Qt::GestureType type, QObject *parent);
+ QGesture(QGesturePrivate &dd, QObject *parent);
private:
friend class QGestureEvent;
@@ -181,8 +180,12 @@ public:
friend class QPinchGestureRecognizer;
};
+QT_END_NAMESPACE
+
Q_DECLARE_METATYPE(QPinchGesture::WhatChanged)
+QT_BEGIN_NAMESPACE
+
class QSwipeGesturePrivate;
class Q_GUI_EXPORT QSwipeGesture : public QGesture
{
@@ -190,8 +193,8 @@ class Q_GUI_EXPORT QSwipeGesture : public QGesture
Q_DECLARE_PRIVATE(QSwipeGesture)
Q_ENUMS(SwipeDirection)
- Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection WRITE setHorizontalDirection)
- Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection WRITE setVerticalDirection)
+ Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection STORED false)
+ Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection STORED false)
Q_PROPERTY(qreal swipeAngle READ swipeAngle WRITE setSwipeAngle)
public:
@@ -200,8 +203,6 @@ public:
SwipeDirection horizontalDirection() const;
SwipeDirection verticalDirection() const;
- void setHorizontalDirection(SwipeDirection value);
- void setVerticalDirection(SwipeDirection value);
qreal swipeAngle() const;
void setSwipeAngle(qreal value);
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index 000f44f..0f0aef2 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -48,6 +48,10 @@
#include "qevent.h"
#include "qgraphicsitem.h"
+#ifdef Q_WS_MAC
+#include "qmacgesturerecognizer_mac_p.h"
+#endif
+
#include "qdebug.h"
// #define GESTURE_DEBUG
@@ -64,7 +68,15 @@ QGestureManager::QGestureManager(QObject *parent)
{
qRegisterMetaType<Qt::GestureState>();
+#if defined(Q_WS_MAC)
+ registerGestureRecognizer(new QMacSwipeGestureRecognizer);
+ registerGestureRecognizer(new QMacPinchGestureRecognizer);
+ #if defined(QT_MAC_USE_COCOA)
+ registerGestureRecognizer(new QMacPanGestureRecognizer);
+ #endif
+#else
registerGestureRecognizer(new QPanGestureRecognizer);
+#endif
}
QGestureManager::~QGestureManager()
@@ -279,8 +291,10 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
QSet<QGesture *> notStarted = finishedGestures - activeGestures;
if (!notStarted.isEmpty()) {
// there are some gestures that claim to be finished, but never started.
- qWarning("QGestureManager::filterEvent: some gestures were finished even though they've never started");
- finishedGestures -= notStarted;
+ // probably those are "singleshot" gestures so we'll fake the started state.
+ foreach (QGesture *gesture, notStarted)
+ gesture->d_func()->state = Qt::GestureStarted;
+ deliverEvents(notStarted, receiver);
}
activeGestures += startedGestures;
diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp
index 590f09e..9de3bcc 100644
--- a/src/gui/kernel/qgesturerecognizer.cpp
+++ b/src/gui/kernel/qgesturerecognizer.cpp
@@ -45,27 +45,156 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class QGestureRecognizer
+ \since 4.6
+ \brief The QGestureRecognizer class provides the infrastructure for gesture recognition.
+ \ingroup gestures
+
+ Gesture recognizers are responsible for creating and managing QGesture objects and
+ monitoring input events sent to QWidget and QGraphicsObject subclasses.
+ QGestureRecognizer is the base class for implementing custom gestures.
+
+ Developers that only need to provide gesture recognition for standard gestures do not
+ need to use this class directly. Instances will be created behind the scenes by the
+ framework.
+
+ \section1 Recognizing Gestures
+
+ The process of recognizing gestures involves filtering input events sent to specific
+ objects, and modifying the associated QGesture objects to include relevant information
+ about the user's input.
+
+ Gestures are created when the framework calls createGesture() to handle user input
+ for a particular instance of a QWidget or QGraphicsObject subclass. A QGesture object
+ is created for each widget or item that is configured to use gestures.
+
+ Once a QGesture has been created for a target object, the gesture recognizer will
+ receive events for it in its filterEvent() handler function.
+
+ When a gesture is canceled, the reset() function is called, giving the recognizer the
+ chance to update the appropriate properties in the corresponding QGesture object.
+
+ \section1 Supporting New Gestures
+
+ To add support for new gestures, you need to derive from QGestureRecognizer to create
+ a custom recognizer class, construct an instance of this class, and register it with
+ the application by calling QApplication::registerGestureRecognizer(). You can also
+ subclass QGesture to create a custom gesture class, or rely on dynamic properties
+ to express specific details of the gesture you want to handle.
+
+ Your custom QGestureRecognizer subclass needs to reimplement the filterEvent() function
+ to handle and filter the incoming input events for QWidget and QGraphicsObject subclasses.
+ Although the logic for gesture recognition is implemented in this function, you can
+ store persistent information about the state of the recognition process in the QGesture
+ object supplied. The filterEvent() function must return a value of Qt::GestureState that
+ indicates the state of recognition for a given gesture and target object. This determines
+ whether or not a gesture event will be delivered to a target object.
+
+ If you choose to represent a gesture by a custom QGesture subclass, you will need to
+ reimplement the createGesture() function to construct instances of your gesture class.
+ Similarly, you may need to reimplement the reset() function if your custom gesture
+ objects need to be specially handled when a gesture is canceled.
+
+ \sa QGesture
+*/
+
+/*!
+ \enum QGestureRecognizer::ResultFlags
+
+ This enum describes the result of the current event filtering step in
+ a gesture recognizer state machine.
+
+ The result consists of a state value (one of Ignore, NotGesture,
+ MaybeGesture, GestureTriggered, GestureFinished) and an optional hint
+ (ConsumeEventHint).
+
+ \value Ignore The event does not change the state of the recognizer.
+
+ \value NotGesture The event made it clear that it is not a gesture. If the
+ gesture recognizer was in GestureTriggered state before, then the gesture
+ is canceled and the appropriate QGesture object will be delivered to the
+ target as a part of a QGestureEvent.
+
+ \value MaybeGesture The event changed the internal state of the recognizer,
+ but it isn't clear yet if it is a gesture or not. The recognizer needs to
+ filter more events to decide. Gesture recognizers in the MaybeGesture state
+ may be reset automatically if they take too long to recognize gestures.
+
+ \value GestureTriggered The gesture has been triggered and the appropriate
+ QGesture object will be delivered to the target as a part of a
+ QGestureEvent.
+
+ \value GestureFinished The gesture has been finished successfully and the
+ appropriate QGesture object will be delivered to the target as a part of a
+ QGestureEvent.
+
+ \value ConsumeEventHint This hint specifies that the gesture framework should
+ consume the filtered event and not deliver it to the receiver.
+
+ \omitvalue ResultState_Mask
+ \omitvalue ResultHint_Mask
+
+ \sa QGestureRecognizer::filterEvent()
+*/
+
+/*!
+ Constructs a new gesture recognizer object.
+*/
QGestureRecognizer::QGestureRecognizer()
{
}
+/*!
+ Destroys the gesture recognizer.
+*/
QGestureRecognizer::~QGestureRecognizer()
{
}
-QGesture *QGestureRecognizer::createGesture(QObject *)
+/*!
+ This function is called by Qt to create a new QGesture object for the
+ given \a target (QWidget or QGraphicsObject).
+
+ Reimplement this function to create a custom QGesture-derived gesture
+ object if necessary.
+*/
+QGesture *QGestureRecognizer::createGesture(QObject *target)
{
+ Q_UNUSED(target);
return new QGesture;
}
-void QGestureRecognizer::reset(QGesture *state)
+/*!
+ This function is called by the framework to reset a given \a gesture.
+
+ Reimplement this function to implement additional requirements for custom QGesture
+ objects. This may be necessary if you implement a custom QGesture whose properties
+ need special handling when the gesture is reset.
+*/
+void QGestureRecognizer::reset(QGesture *gesture)
{
- if (state) {
- QGesturePrivate *d = state->d_func();
+ if (gesture) {
+ QGesturePrivate *d = gesture->d_func();
d->state = Qt::NoGesture;
d->hotSpot = QPointF();
d->targetObject = 0;
}
}
+/*!
+ \fn QGestureRecognizer::filterEvent(QGesture *gesture, QObject *watched, QEvent *event)
+
+ Handles the given \a event for the \a watched object, updating the state of the \a gesture
+ object as required, and returns a suitable Result for the current recognition step.
+
+ This function is called by the framework to allow the recognizer to filter input events
+ dispatched to QWidget or QGraphicsObject instances that it is monitoring.
+
+ The result reflects how much of the gesture has been recognized. The state of the
+ \a gesture object is set depending on the result.
+
+ \sa Qt::GestureState
+*/
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h
index c85afd2..efd8565 100644
--- a/src/gui/kernel/qgesturerecognizer.h
+++ b/src/gui/kernel/qgesturerecognizer.h
@@ -42,7 +42,7 @@
#ifndef QGESTURERECOGNIZER_H
#define QGESTURERECOGNIZER_H
-#include "qglobal.h"
+#include <QtCore/qglobal.h>
QT_BEGIN_HEADER
diff --git a/src/gui/kernel/qmacgesturerecognizer_mac.mm b/src/gui/kernel/qmacgesturerecognizer_mac.mm
new file mode 100644
index 0000000..7b19a54
--- /dev/null
+++ b/src/gui/kernel/qmacgesturerecognizer_mac.mm
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmacgesturerecognizer_mac_p.h"
+#include "qgesture.h"
+#include "qgesture_p.h"
+#include "qevent.h"
+#include "qevent_p.h"
+#include "qwidget.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+QMacSwipeGestureRecognizer::QMacSwipeGestureRecognizer()
+{
+}
+
+QGesture *QMacSwipeGestureRecognizer::createGesture(QObject * /*target*/)
+{
+ return new QSwipeGesture;
+}
+
+QGestureRecognizer::Result
+QMacSwipeGestureRecognizer::filterEvent(QGesture *gesture, QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::NativeGesture && obj->isWidgetType()) {
+ QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
+ switch (ev->gestureType) {
+ case QNativeGestureEvent::Swipe: {
+ QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture);
+ g->setSwipeAngle(ev->angle);
+ return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint;
+ break; }
+ default:
+ break;
+ }
+ }
+
+ return QGestureRecognizer::Ignore;
+}
+
+void QMacSwipeGestureRecognizer::reset(QGesture *gesture)
+{
+ QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture);
+ g->setSwipeAngle(0);
+ QGestureRecognizer::reset(gesture);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+QMacPinchGestureRecognizer::QMacPinchGestureRecognizer()
+{
+}
+
+QGesture *QMacPinchGestureRecognizer::createGesture(QObject * /*target*/)
+{
+ return new QPinchGesture;
+}
+
+QGestureRecognizer::Result
+QMacPinchGestureRecognizer::filterEvent(QGesture *gesture, QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::NativeGesture && obj->isWidgetType()) {
+ QPinchGesture *g = static_cast<QPinchGesture *>(gesture);
+ QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
+ switch(ev->gestureType) {
+ case QNativeGestureEvent::GestureBegin:
+ reset(gesture);
+ g->setStartCenterPoint(static_cast<QWidget*>(obj)->mapFromGlobal(ev->position));
+ g->setCenterPoint(g->startCenterPoint());
+ g->setWhatChanged(QPinchGesture::CenterPointChanged);
+ return QGestureRecognizer::MaybeGesture | QGestureRecognizer::ConsumeEventHint;
+ case QNativeGestureEvent::Rotate: {
+ g->setLastScaleFactor(g->scaleFactor());
+ g->setLastRotationAngle(g->rotationAngle());
+ g->setRotationAngle(g->rotationAngle() + ev->percentage);
+ g->setWhatChanged(QPinchGesture::RotationAngleChanged);
+ return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint;
+ break;
+ }
+ case QNativeGestureEvent::Zoom:
+ g->setLastScaleFactor(g->scaleFactor());
+ g->setLastRotationAngle(g->rotationAngle());
+ g->setScaleFactor(g->scaleFactor() + ev->percentage);
+ g->setWhatChanged(QPinchGesture::ScaleFactorChanged);
+ return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint;
+ break;
+ case QNativeGestureEvent::GestureEnd:
+ return QGestureRecognizer::GestureFinished | QGestureRecognizer::ConsumeEventHint;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return QGestureRecognizer::Ignore;
+}
+
+void QMacPinchGestureRecognizer::reset(QGesture *gesture)
+{
+ QPinchGesture *g = static_cast<QPinchGesture *>(gesture);
+ g->setWhatChanged(0);
+ g->setScaleFactor(1.0f);
+ g->setTotalScaleFactor(1.0f);
+ g->setLastScaleFactor(1.0f);
+ g->setRotationAngle(0.0f);
+ g->setTotalRotationAngle(0.0f);
+ g->setLastRotationAngle(0.0f);
+ g->setCenterPoint(QPointF());
+ g->setStartCenterPoint(QPointF());
+ g->setLastCenterPoint(QPointF());
+ QGestureRecognizer::reset(gesture);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+#if defined(QT_MAC_USE_COCOA)
+
+QMacPanGestureRecognizer::QMacPanGestureRecognizer() : _panCanceled(true)
+{
+}
+
+QGesture *QMacPanGestureRecognizer::createGesture(QObject *target)
+{
+ if (!target)
+ return new QPanGesture;
+
+ if (QWidget *w = qobject_cast<QWidget *>(target)) {
+ w->setAttribute(Qt::WA_AcceptTouchEvents);
+ w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
+ return new QPanGesture;
+ }
+ return 0;
+}
+
+QGestureRecognizer::Result
+QMacPanGestureRecognizer::filterEvent(QGesture *gesture, QObject *target, QEvent *event)
+{
+ const int panBeginDelay = 300;
+ const int panBeginRadius = 3;
+
+ QPanGesture *g = static_cast<QPanGesture *>(gesture);
+
+ switch (event->type()) {
+ case QEvent::TouchBegin: {
+ const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
+ if (ev->touchPoints().size() == 1) {
+ reset(gesture);
+ _startPos = QCursor::pos();
+ _lastPos = _startPos;
+ _panTimer.start(panBeginDelay, target);
+ _panCanceled = false;
+ return QGestureRecognizer::MaybeGesture;
+ }
+ break;}
+ case QEvent::TouchEnd: {
+ if (_panCanceled)
+ break;
+
+ const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
+ if (ev->touchPoints().size() == 1)
+ return QGestureRecognizer::GestureFinished;
+ break;}
+ case QEvent::TouchUpdate: {
+ if (_panCanceled)
+ break;
+
+ const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
+ if (ev->touchPoints().size() == 1) {
+ if (_panTimer.isActive()) {
+ // INVARIANT: Still in maybeGesture. Check if the user
+ // moved his finger so much that it makes sense to cancel the pan:
+ const QPointF p = QCursor::pos();
+ if ((p - _startPos).manhattanLength() > panBeginRadius) {
+ _panCanceled = true;
+ _panTimer.stop();
+ return QGestureRecognizer::NotGesture;
+ }
+ } else {
+ const QPointF p = QCursor::pos();
+ const QPointF posOffset = p - _lastPos;
+ g->setLastOffset(g->offset());
+ g->setOffset(QSizeF(posOffset.x(), posOffset.y()));
+ g->setTotalOffset(g->lastOffset() + g->offset());
+ _lastPos = p;
+ return QGestureRecognizer::GestureTriggered;
+ }
+ } else if (_panTimer.isActive()) {
+ // I only want to cancel the pan if the user is pressing
+ // more than one finger, and the pan hasn't started yet:
+ _panCanceled = true;
+ _panTimer.stop();
+ return QGestureRecognizer::NotGesture;
+ }
+ break;}
+ case QEvent::Timer: {
+ QTimerEvent *ev = static_cast<QTimerEvent *>(event);
+ if (ev->timerId() == _panTimer.timerId()) {
+ _panTimer.stop();
+ if (_panCanceled)
+ break;
+ // Begin new pan session!
+ _startPos = QCursor::pos();
+ _lastPos = _startPos;
+ return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint;
+ }
+ break; }
+ default:
+ break;
+ }
+
+ return QGestureRecognizer::Ignore;
+}
+
+void QMacPanGestureRecognizer::reset(QGesture *gesture)
+{
+ QPanGesture *g = static_cast<QPanGesture *>(gesture);
+ _startPos = QPointF();
+ _lastPos = QPointF();
+ _panCanceled = true;
+ g->setOffset(QSizeF(0, 0));
+ g->setLastOffset(QSizeF(0, 0));
+ g->setTotalOffset(QSizeF(0, 0));
+ g->setAcceleration(qreal(1));
+ QGestureRecognizer::reset(gesture);
+}
+#endif // QT_MAC_USE_COCOA
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qmacgesturerecognizer_mac_p.h b/src/gui/kernel/qmacgesturerecognizer_mac_p.h
new file mode 100644
index 0000000..bdc2e08
--- /dev/null
+++ b/src/gui/kernel/qmacgesturerecognizer_mac_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMACSWIPEGESTURERECOGNIZER_MAC_P_H
+#define QMACSWIPEGESTURERECOGNIZER_MAC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtimer.h"
+#include "qpoint.h"
+#include "qgesturerecognizer.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMacSwipeGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QMacSwipeGestureRecognizer();
+
+ QGesture *createGesture(QObject *target);
+ QGestureRecognizer::Result filterEvent(QGesture *gesture, QObject *watched, QEvent *event);
+ void reset(QGesture *gesture);
+};
+
+class QMacPinchGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QMacPinchGestureRecognizer();
+
+ QGesture *createGesture(QObject *target);
+ QGestureRecognizer::Result filterEvent(QGesture *gesture, QObject *watched, QEvent *event);
+ void reset(QGesture *gesture);
+};
+
+#if defined(QT_MAC_USE_COCOA)
+
+class QMacPanGestureRecognizer : public QObject, public QGestureRecognizer
+{
+public:
+ QMacPanGestureRecognizer();
+
+ QGesture *createGesture(QObject *target);
+ QGestureRecognizer::Result filterEvent(QGesture *gesture, QObject *watched, QEvent *event);
+ void reset(QGesture *gesture);
+private:
+ QPointF _startPos;
+ QPointF _lastPos;
+ QBasicTimer _panTimer;
+ bool _panCanceled;
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QMACSWIPEGESTURERECOGNIZER_MAC_P_H
diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp
index 1214f08..6116a5e 100644
--- a/src/gui/kernel/qsoftkeymanager.cpp
+++ b/src/gui/kernel/qsoftkeymanager.cpp
@@ -125,7 +125,6 @@ QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *act
break;
}
action->setSoftKeyRole(softKeyRole);
- action->setEnabled(actionWidget->isEnabled());
return action;
}
@@ -210,7 +209,7 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys)
for (int index = 0; index < softkeys.count(); index++) {
const QAction* softKeyAction = softkeys.at(index);
switch (softKeyAction->softKeyRole()) {
- // Positive Actions go on LSK
+ // Positive Actions on the LSK
case QAction::PositiveSoftKey:
position = 0;
break;
@@ -253,7 +252,8 @@ bool QSoftKeyManager::handleCommand(int command)
QAction *action = softKeys.at(i);
if (action->softKeyRole() != QAction::NoSoftKey) {
if (j == index) {
- if (action->isEnabled()) {
+ QWidget *parent = action->parentWidget();
+ if (parent && parent->isEnabled()) {
action->activate(QAction::Trigger);
return true;
}
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index bce06e0..8da415f 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1502,6 +1502,8 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier
mapper->remove(data.winid);
}
+ const WId oldWinId = data.winid;
+
data.winid = id;
#if defined(Q_WS_X11)
hd = id; // X11: hd == ident
@@ -1509,6 +1511,16 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier
if (mapper && id && !userDesktopWidget) {
mapper->insert(data.winid, q);
}
+
+ if(oldWinId != id) {
+ // Do not emit an event when the old winId is destroyed. This only
+ // happens (a) during widget destruction, and (b) immediately prior
+ // to creation of a new winId, for example as a result of re-parenting.
+ if(id != 0) {
+ QEvent e(QEvent::WinIdChange);
+ QCoreApplication::sendEvent(q, &e);
+ }
+ }
}
void QWidgetPrivate::createTLExtra()
@@ -2227,8 +2239,8 @@ QWidget *QWidget::find(WId id)
against. If Qt is using Carbon, the {WId} is actually an HIViewRef. If Qt
is using Cocoa, {WId} is a pointer to an NSView.
- \note We recommend that you do not store this value as it is likely to
- change at run-time.
+ This value may change at run-time. An event with type QEvent::WinIdChange
+ will be sent to the widget following a change in window system identifier.
\sa find()
*/
@@ -11672,10 +11684,16 @@ QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
Synonym for QList<QWidget *>.
*/
-void QWidget::grabGesture(Qt::GestureType type, Qt::GestureContext context)
+/*!
+ Subscribes the widget to a given \a gesture with a \a context.
+
+ \sa QGestureEvent
+ \since 4.6
+*/
+void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureContext context)
{
Q_D(QWidget);
- d->gestureContext.insert(type, context);
+ d->gestureContext.insert(gesture, context);
(void)QGestureManager::instance(); // create a gesture manager
}
@@ -11992,3 +12010,10 @@ void QWidget::clearMask()
XRender extension is not supported on the X11 display, or if the
handle could not be created.
*/
+
+#ifdef Q_OS_SYMBIAN
+void QWidgetPrivate::_q_delayedDestroy(WId winId)
+{
+ delete winId;
+}
+#endif
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 3501c6e..e603a1a 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -726,14 +726,11 @@ private:
friend class QGLContext;
friend class QGLWidget;
friend class QGLWindowSurface;
- friend class QGLWindowSurfaceGLPaintDevice;
- friend class QVGWindowSurface;
friend class QX11PaintEngine;
friend class QWin32PaintEngine;
friend class QShortcutPrivate;
friend class QShortcutMap;
friend class QWindowSurface;
- friend class QD3DWindowSurface;
friend class QGraphicsProxyWidget;
friend class QGraphicsProxyWidgetPrivate;
friend class QStyleSheetStyle;
@@ -776,6 +773,9 @@ private:
private:
Q_DISABLE_COPY(QWidget)
Q_PRIVATE_SLOT(d_func(), void _q_showIfNotHidden())
+#ifdef Q_OS_SYMBIAN
+ Q_PRIVATE_SLOT(d_func(), void _q_delayedDestroy(WId winId))
+#endif
QWidgetData *data;
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index a549740..f7c2712 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -296,7 +296,8 @@ public:
void setMask_sys(const QRegion &);
#ifdef Q_OS_SYMBIAN
void setSoftKeys_sys(const QList<QAction*> &softkeys);
- void activateSymbianWindow();
+ void activateSymbianWindow(WId wid = 0);
+ void _q_delayedDestroy(WId winId);
#endif
void raise_sys();
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index b0d405a..8ce5001 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -56,6 +56,12 @@
#include <aknappui.h>
#endif
+// This is necessary in order to be able to perform delayed invokation on slots
+// which take arguments of type WId. One example is
+// QWidgetPrivate::_q_delayedDestroy, which is used to delay destruction of
+// CCoeControl objects until after the CONE event handler has finished running.
+Q_DECLARE_METATYPE(WId)
+
QT_BEGIN_NAMESPACE
extern bool qt_nograb();
@@ -318,8 +324,6 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
bool desktop = (type == Qt::Desktop);
//bool tool = (type == Qt::Tool || type == Qt::Drawer);
- WId id = 0;
-
if (popup)
flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
@@ -341,13 +345,10 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
data.crect.setSize(QSize(width, height));
}
- CCoeControl *destroyw = 0;
+ CCoeControl *const destroyw = destroyOldWindow ? data.winid : 0;
createExtra();
if (window) {
- if (destroyOldWindow)
- destroyw = data.winid;
- id = window;
setWinId(window);
TRect tr = window->Rect();
data.crect.setRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height());
@@ -355,10 +356,15 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
} else if (topLevel) {
if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen))
data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY));
- QSymbianControl *control= q_check_ptr(new QSymbianControl(q));
- id = (WId)control;
- setWinId(id);
- QT_TRAP_THROWING(control->ConstructL(true,desktop));
+
+ QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
+ QT_TRAP_THROWING(control->ConstructL(true, desktop));
+
+ // Symbian windows are always created in an inactive state
+ // We perform this assignment for the case where the window is being re-created
+ // as aa result of a call to setParent_sys, on either this widget or one of its
+ // ancestors.
+ extra->activated = 0;
if (!desktop) {
TInt stackingFlags;
@@ -368,7 +374,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
stackingFlags = ECoeStackFlagStandard;
}
control->MakeVisible(false);
- QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags));
+ QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags));
// Avoid keyboard focus to a hidden window.
control->setFocusSafely(false);
@@ -391,11 +397,22 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
int x, y, w, h;
data.crect.getRect(&x, &y, &w, &h);
control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+
+ // We wait until the control is fully constructed before calling setWinId, because
+ // this generates a WinIdChanged event.
+ setWinId(control.take());
+
} else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget
- QSymbianControl *control = new QSymbianControl(q);
- setWinId(control);
+
+ QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
QT_TRAP_THROWING(control->ConstructL(!parentWidget));
+ // Symbian windows are always created in an inactive state
+ // We perform this assignment for the case where the window is being re-created
+ // as aa result of a call to setParent_sys, on either this widget or one of its
+ // ancestors.
+ extra->activated = 0;
+
TInt stackingFlags;
if ((q->windowType() & Qt::Popup) == Qt::Popup) {
stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus;
@@ -403,7 +420,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
stackingFlags = ECoeStackFlagStandard;
}
control->MakeVisible(false);
- QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags));
+ QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags));
// Avoid keyboard focus to a hidden window.
control->setFocusSafely(false);
@@ -418,12 +435,21 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
| EPointerFilterMove | EPointerFilterDrag, 0);
if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
- activateSymbianWindow();
+ activateSymbianWindow(control.data());
+
+ // We wait until the control is fully constructed before calling setWinId, because
+ // this generates a WinIdChanged event.
+ setWinId(control.take());
}
if (destroyw) {
destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw);
- CBase::Delete(destroyw);
+
+ // Delay deletion of the control in case this function is called in the
+ // context of a CONE event handler such as
+ // CCoeControl::ProcessPointerEventL
+ QMetaObject::invokeMethod(q, "_q_delayedDestroy",
+ Qt::QueuedConnection, Q_ARG(WId, destroyw));
}
if (q->testAttribute(Qt::WA_AcceptTouchEvents))
@@ -468,7 +494,7 @@ void QWidgetPrivate::show_sys()
invalidateBuffer(q->rect());
}
-void QWidgetPrivate::activateSymbianWindow()
+void QWidgetPrivate::activateSymbianWindow(WId wid)
{
Q_Q(QWidget);
@@ -476,8 +502,12 @@ void QWidgetPrivate::activateSymbianWindow()
Q_ASSERT(q->testAttribute(Qt::WA_Mapped));
Q_ASSERT(!extra->activated);
- WId id = q->internalWinId();
- QT_TRAP_THROWING(id->ActivateL());
+ if(!wid)
+ wid = q->internalWinId();
+
+ Q_ASSERT(wid);
+
+ QT_TRAP_THROWING(wid->ActivateL());
extra->activated = 1;
}
@@ -571,8 +601,14 @@ void QWidgetPrivate::reparentChildren()
w->d_func()->invalidateBuffer(w->rect());
WId parent = q->effectiveWinId();
WId child = w->effectiveWinId();
- if (parent != child)
- child->SetParent(parent);
+ if (parent != child) {
+ // Child widget is native. Because Symbian windows cannot be
+ // re-parented, we must re-create the window.
+ const WId window = 0;
+ const bool initializeWindow = false;
+ const bool destroyOldWindow = true;
+ w->d_func()->create_sys(window, initializeWindow, destroyOldWindow);
+ }
// ### TODO: We probably also need to update the component array here
w->d_func()->reparentChildren();
} else {