summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@digia.com>2013-10-02 08:52:26 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-17 15:58:32 +0200
commitfbfc8ffbf39e2e7a540d4d576ec61bea7db63416 (patch)
tree5df0b25a1fae3e88a538075c857e5cc3bcc18a03 /src
parent73e3d2f6cb002be4ce409c3738db74b61beb12f4 (diff)
Implement native gestures on OS X.
Add QWindowSystemInterface::GestureEvent and QNativeGestureEvent to QtGui. These events are copies of Qt4's QNativeGestureEvent, where it was an implementation detail of QGestureManager. Add gesture message handlers to QNSView and bring back the Mac gesture recognizers for QGestureManager. Task-number: QTBUG-28126 Change-Id: I1304e09e776fa7c44d133d54ca8b895ca2f544c5 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qnamespace.h12
-rw-r--r--src/corelib/kernel/qcoreevent.h2
-rw-r--r--src/gui/kernel/qevent.cpp115
-rw-r--r--src/gui/kernel/qevent.h28
-rw-r--r--src/gui/kernel/qguiapplication.cpp13
-rw-r--r--src/gui/kernel/qguiapplication_p.h1
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp29
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h9
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h16
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm96
-rw-r--r--src/widgets/kernel/kernel.pri56
-rw-r--r--src/widgets/kernel/qgesture_p.h35
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp6
-rw-r--r--src/widgets/kernel/qmacgesturerecognizer.cpp275
-rw-r--r--src/widgets/kernel/qmacgesturerecognizer_p.h102
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp27
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa_p.h3
17 files changed, 733 insertions, 92 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index e2c6039989..8a46f3a6ab 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1557,6 +1557,18 @@ public:
IgnoredGesturesPropagateToParent = 0x04
};
Q_DECLARE_FLAGS(GestureFlags, GestureFlag)
+
+ enum NativeGestureType
+ {
+ BeginNativeGesture,
+ EndNativeGesture,
+ PanNativeGesture,
+ ZoomNativeGesture,
+ SmartZoomNativeGesture,
+ RotateNativeGesture,
+ SwipeNativeGesture
+ };
+
#endif // QT_NO_GESTURES
enum NavigationMode
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 2ca0a7d0b0..e974c4d226 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -249,7 +249,7 @@ public:
TouchEnd = 196,
#ifndef QT_NO_GESTURES
- NativeGesture = 197, // Internal for platform gesture support
+ NativeGesture = 197, // QtGui native gesture
#endif
RequestSoftwareInputPanel = 199,
CloseSoftwareInputPanel = 200,
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index ef9a3a1225..06fa1f3550 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -2263,6 +2263,121 @@ QTabletEvent::~QTabletEvent()
#endif // QT_NO_TABLETEVENT
+/*!
+ \class QNativeGestureEvent
+ \since 5.2
+ \brief The QNativeGestureEvent class contains parameters that describe a gesture event.
+ \inmodule QtGui
+ \ingroup events
+
+ Native gesture events are generated by the operating system, typically by
+ interpreting touch events. Gesture events are high-level events such
+ as zoom or rotate.
+
+ \table
+ \header
+ \li Event Type
+ \li Description
+ \li Touch equence
+ \row
+ \li Qt::ZoomNativeGesture
+ \li Magnification delta in percent.
+ \li OS X: Two-finger pinch.
+ \row
+ \li Qt::SmartZoomNativeGesture
+ \li Boolean magnification state.
+ \li OS X: Two-finger douple tap (trackpad) / One-finger douple tap (magic mouse).
+ \row
+ \li Qt::RotateNativeGesture
+ \li Rotation delta in degrees.
+ \li OS X: Two-finger rotate.
+ \endtable
+
+
+ In addition, BeginNativeGesture and EndNativeGesture are sent before and after
+ gesture event streams:
+
+ BeginNativeGesture
+ ZoomNativeGesture
+ ZoomNativeGesture
+ ZoomNativeGesture
+ EndNativeGesture
+
+ \sa Qt::NativeGestureType, QGestureEvent
+*/
+
+/*!
+ Constructs a native gesture event of type \a type.
+
+ The points \a localPos, \a windowPos and \a screenPos specify the
+ gesture position relative to the receiving widget or item,
+ window, and screen, respectively.
+
+ \a realValue is the OS X event parameter, \a sequenceId and \a intValue are the Windows event parameters.
+*/
+QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QPointF &localPos, const QPointF &windowPos,
+ const QPointF &screenPos, qreal realValue, ulong sequenceId, quint64 intValue)
+ : QInputEvent(QEvent::NativeGesture), mGestureType(type),
+ mLocalPos(localPos), mWindowPos(windowPos), mScreenPos(screenPos), mRealValue(realValue),
+ mSequenceId(sequenceId), mIntValue(intValue)
+{ }
+
+/*!
+ \fn QNativeGestureEvent::gestureType() const
+ \since 5.2
+
+ Returns the gesture type.
+*/
+
+/*!
+ \fn QNativeGestureEvent::value() const
+ \since 5.2
+
+ Returns the gesture value. The value should be interpreted based on the
+ gesture type. For example, a Zoom gesture provides a scale factor while a Rotate
+ gesture provides a rotation delta.
+
+ \sa QNativeGestureEvent, gestureType()
+*/
+
+/*!
+ \fn QPoint QNativeGestureEvent::globalPos() const
+ \since 5.2
+
+ Returns the position of the gesture as a QPointF in screen coordinates
+*/
+
+/*!
+ \fn QPoint QNativeGestureEvent::pos() const
+ \since 5.2
+
+ Returns the position of the mouse cursor, relative to the widget
+ or item that received the event.
+*/
+
+/*!
+ \fn QPointF QNativeGestureEvent::localPos() const
+ \since 5.2
+
+ Returns the position of the gesture as a QPointF, relative to the
+ widget or item that received the event.
+*/
+
+/*!
+ \fn QPointF QNativeGestureEvent::screenPos() const
+ \since 5.2
+
+ Returns the position of the gesture as a QPointF in screen coordinates.
+*/
+
+/*!
+ \fn QPointF QNativeGestureEvent::windowPos() const
+ \since 5.2
+
+ Returns the position of the gesture as a QPointF, relative to the
+ window that received the event.
+*/
+
#ifndef QT_NO_DRAGANDDROP
/*!
Creates a QDragMoveEvent of the required \a type indicating
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 0c1cf70420..d22e423248 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -268,6 +268,34 @@ protected:
};
#endif // QT_NO_TABLETEVENT
+#ifndef QT_NO_GESTURES
+class Q_GUI_EXPORT QNativeGestureEvent : public QInputEvent
+{
+public:
+ QNativeGestureEvent(Qt::NativeGestureType type, const QPointF &localPos, const QPointF &windowPos,
+ const QPointF &screenPos, qreal value, ulong sequenceId, quint64 intArgument);
+ Qt::NativeGestureType gestureType() const { return mGestureType; }
+ qreal value() const { return mRealValue; }
+
+#ifndef QT_NO_INTEGER_EVENT_COORDINATES
+ inline const QPoint pos() const { return mLocalPos.toPoint(); }
+ inline const QPoint globalPos() const { return mScreenPos.toPoint(); }
+#endif
+ const QPointF &localPos() const { return mLocalPos; }
+ const QPointF &windowPos() const { return mWindowPos; }
+ const QPointF &screenPos() const { return mScreenPos; }
+
+protected:
+ Qt::NativeGestureType mGestureType;
+ QPointF mLocalPos;
+ QPointF mWindowPos;
+ QPointF mScreenPos;
+ qreal mRealValue;
+ ulong mSequenceId;
+ quint64 mIntValue;
+};
+#endif // QT_NO_GESTURES
+
class Q_GUI_EXPORT QKeyEvent : public QInputEvent
{
public:
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 1e3ea3092f..d254f7c9bc 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1473,6 +1473,10 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
QGuiApplicationPrivate::processTabletLeaveProximityEvent(
static_cast<QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *>(e));
break;
+ case QWindowSystemInterfacePrivate::Gesture:
+ QGuiApplicationPrivate::processGestureEvent(
+ static_cast<QWindowSystemInterfacePrivate::GestureEvent *>(e));
+ break;
case QWindowSystemInterfacePrivate::PlatformPanel:
QGuiApplicationPrivate::processPlatformPanelEvent(
static_cast<QWindowSystemInterfacePrivate::PlatformPanelEvent *>(e));
@@ -1958,6 +1962,15 @@ void QGuiApplicationPrivate::processTabletLeaveProximityEvent(QWindowSystemInter
#endif
}
+#ifndef QT_NO_GESTURES
+void QGuiApplicationPrivate::processGestureEvent(QWindowSystemInterfacePrivate::GestureEvent *e)
+{
+ QNativeGestureEvent ev(e->type, e->pos, e->pos, e->globalPos, e->realValue, e->sequenceId, e->intValue);
+ ev.setTimestamp(e->timestamp);
+ QGuiApplication::sendSpontaneousEvent(e->window, &ev);
+}
+#endif // QT_NO_GESTURES
+
void QGuiApplicationPrivate::processPlatformPanelEvent(QWindowSystemInterfacePrivate::PlatformPanelEvent *e)
{
if (!e->window)
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index d1716a6e28..65c6d814e6 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -148,6 +148,7 @@ public:
static void processTabletEvent(QWindowSystemInterfacePrivate::TabletEvent *e);
static void processTabletEnterProximityEvent(QWindowSystemInterfacePrivate::TabletEnterProximityEvent *e);
static void processTabletLeaveProximityEvent(QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e);
+ static void processGestureEvent(QWindowSystemInterfacePrivate::GestureEvent *e);
static void processPlatformPanelEvent(QWindowSystemInterfacePrivate::PlatformPanelEvent *e);
#ifndef QT_NO_CONTEXTMENU
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index d62330083e..902c32419d 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -669,6 +669,35 @@ void QWindowSystemInterface::handleTabletLeaveProximityEvent(int device, int poi
handleTabletLeaveProximityEvent(time, device, pointerType, uid);
}
+#ifndef QT_NO_GESTURES
+void QWindowSystemInterface::handleGestureEvent(QWindow *window, ulong timestamp, Qt::NativeGestureType type,
+ QPointF &local, QPointF &global)
+{
+ QWindowSystemInterfacePrivate::GestureEvent *e =
+ new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, local, global);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+}
+
+void QWindowSystemInterface::handleGestureEventWithRealValue(QWindow *window, ulong timestamp, Qt::NativeGestureType type,
+ qreal value, QPointF &local, QPointF &global)
+{
+ QWindowSystemInterfacePrivate::GestureEvent *e =
+ new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, local, global);
+ e->realValue = value;
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+}
+
+void QWindowSystemInterface::handleGestureEventWithSequenceIdAndValue(QWindow *window, ulong timestamp, Qt::NativeGestureType type,
+ ulong sequenceId, quint64 value, QPointF &local, QPointF &global)
+{
+ QWindowSystemInterfacePrivate::GestureEvent *e =
+ new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, local, global);
+ e->sequenceId = sequenceId;
+ e->intValue = value;
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+}
+#endif // QT_NO_GESTURES
+
void QWindowSystemInterface::handlePlatformPanelEvent(QWindow *w)
{
QWindowSystemInterfacePrivate::PlatformPanelEvent *e =
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index c8e464f985..d8d0922b96 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -177,6 +177,15 @@ public:
static void handleTabletLeaveProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid);
static void handleTabletLeaveProximityEvent(int device, int pointerType, qint64 uid);
+#ifndef QT_NO_GESTURES
+ static void handleGestureEvent(QWindow *window, ulong timestamp, Qt::NativeGestureType type,
+ QPointF &local, QPointF &global);
+ static void handleGestureEventWithRealValue(QWindow *window, ulong timestamp, Qt::NativeGestureType type,
+ qreal value, QPointF &local, QPointF &global);
+ static void handleGestureEventWithSequenceIdAndValue(QWindow *window, ulong timestamp,Qt::NativeGestureType type,
+ ulong sequenceId, quint64 value, QPointF &local, QPointF &global);
+#endif // QT_NO_GESTURES
+
static void handlePlatformPanelEvent(QWindow *w);
#ifndef QT_NO_CONTEXTMENU
static void handleContextMenuEvent(QWindow *w, bool mouseTriggered,
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index 46479701cc..03e2d420f0 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -91,6 +91,7 @@ public:
PlatformPanel = UserInputEvent | 0x17,
ContextMenu = UserInputEvent | 0x18,
EnterWhatsThisMode = UserInputEvent | 0x19,
+ Gesture = UserInputEvent | 0x1a,
ApplicationStateChanged = 0x19,
FlushEvents = 0x20,
WindowScreenChanged = 0x21
@@ -398,6 +399,21 @@ public:
};
#endif
+ class GestureEvent : public InputEvent {
+ public:
+ GestureEvent(QWindow *window, ulong time, Qt::NativeGestureType type, QPointF pos, QPointF globalPos)
+ : InputEvent(window, time, Gesture, Qt::NoModifier), type(type), pos(pos), globalPos(globalPos),
+ realValue(0), sequenceId(0), intValue(0) { }
+ Qt::NativeGestureType type;
+ QPointF pos;
+ QPointF globalPos;
+ // Mac
+ qreal realValue;
+ // Windows
+ ulong sequenceId;
+ quint64 intValue;
+ };
+
class WindowSystemEventList {
QList<WindowSystemEvent *> impl;
mutable QMutex mutex;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index f471a61aa0..f90fc6b205 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -975,6 +975,102 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
QWindowSystemInterface::handleTouchEvent(m_window, timestamp * 1000, touchDevice, points);
}
+#ifndef QT_NO_GESTURES
+//#define QT_COCOA_ENABLE_GESTURE_DEBUG
+- (void)magnifyWithEvent:(NSEvent *)event
+{
+#ifdef QT_COCOA_ENABLE_GESTURE_DEBUG
+ qDebug() << "magnifyWithEvent" << [event magnification];
+#endif
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromEvent:event toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::ZoomNativeGesture,
+ [event magnification], windowPoint, screenPoint);
+}
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
+- (void)smartMagnifyWithEvent:(NSEvent *)event
+{
+ static bool zoomIn = true;
+#ifdef QT_COCOA_ENABLE_GESTURE_DEBUG
+ qDebug() << "smartMagnifyWithEvent" << zoomIn;
+#endif
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromEvent:event toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::SmartZoomNativeGesture,
+ zoomIn ? 1.0f : 0.0f, windowPoint, screenPoint);
+ zoomIn = !zoomIn;
+}
+#endif
+
+- (void)rotateWithEvent:(NSEvent *)event
+{
+#ifdef QT_COCOA_ENABLE_GESTURE_DEBUG
+ qDebug() << "rotateWithEvent" << [event rotation];
+#endif
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromEvent:event toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::RotateNativeGesture,
+ -[event rotation], windowPoint, screenPoint);
+}
+
+- (void)swipeWithEvent:(NSEvent *)event
+{
+#ifdef QT_COCOA_ENABLE_GESTURE_DEBUG
+ qDebug() << "swipeWithEvent" << [event deltaX] << [event deltaY];
+#endif
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromEvent:event toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+
+ qreal angle = 0.0f;
+ if ([event deltaX] == 1)
+ angle = 180.0f;
+ else if ([event deltaX] == -1)
+ angle = 0.0f;
+ else if ([event deltaY] == 1)
+ angle = 90.0f;
+ else if ([event deltaY] == -1)
+ angle = 270.0f;
+
+ QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::SwipeNativeGesture,
+ angle, windowPoint, screenPoint);
+}
+
+- (void)beginGestureWithEvent:(NSEvent *)event
+{
+#ifdef QT_COCOA_ENABLE_GESTURE_DEBUG
+ qDebug() << "beginGestureWithEvent";
+#endif
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromEvent:event toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleGestureEvent(m_window, timestamp, Qt::BeginNativeGesture,
+ windowPoint, screenPoint);
+}
+
+- (void)endGestureWithEvent:(NSEvent *)event
+{
+#ifdef QT_COCOA_ENABLE_GESTURE_DEBUG
+ qDebug() << "endGestureWithEvent";
+#endif
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromEvent:event toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleGestureEvent(m_window, timestamp, Qt::EndNativeGesture,
+ windowPoint, screenPoint);
+}
+#endif // QT_NO_GESTURES
+
#ifndef QT_NO_WHEELEVENT
- (void)scrollWheel:(NSEvent *)theEvent
{
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri
index 533b696faa..444b9b687f 100644
--- a/src/widgets/kernel/kernel.pri
+++ b/src/widgets/kernel/kernel.pri
@@ -66,59 +66,9 @@ SOURCES += \
kernel/qwidgetwindow.cpp \
kernel/qwindowcontainer.cpp
-
-# TODO
-false:!x11:mac {
- SOURCES += \
- kernel/qclipboard_mac.cpp \
- kernel/qmime_mac.cpp \
- kernel/qt_mac.cpp \
- kernel/qkeymapper_mac.cpp
-
- OBJECTIVE_HEADERS += \
- qcocoawindow_mac_p.h \
- qcocoapanel_mac_p.h \
- qcocoawindowdelegate_mac_p.h \
- qcocoaview_mac_p.h \
- qcocoaapplication_mac_p.h \
- qcocoaapplicationdelegate_mac_p.h \
- qmacgesturerecognizer_mac_p.h \
- qmultitouch_mac_p.h \
- qcocoasharedwindowmethods_mac_p.h \
- qcocoaintrospection_p.h
-
- OBJECTIVE_SOURCES += \
- kernel/qcursor_mac.mm \
- kernel/qdnd_mac.mm \
- kernel/qapplication_mac.mm \
- kernel/qwidget_mac.mm \
- kernel/qcocoapanel_mac.mm \
- kernel/qcocoaview_mac.mm \
- kernel/qcocoawindow_mac.mm \
- kernel/qcocoawindowdelegate_mac.mm \
- kernel/qcocoaapplication_mac.mm \
- kernel/qcocoaapplicationdelegate_mac.mm \
- kernel/qt_cocoa_helpers_mac.mm \
- kernel/qdesktopwidget_mac.mm \
- kernel/qeventdispatcher_mac.mm \
- kernel/qcocoawindowcustomthemeframe_mac.mm \
- kernel/qmacgesturerecognizer_mac.mm \
- kernel/qmultitouch_mac.mm \
- kernel/qcocoaintrospection_mac.mm
-
- HEADERS += \
- kernel/qt_cocoa_helpers_mac_p.h \
- kernel/qcocoaapplication_mac_p.h \
- kernel/qcocoaapplicationdelegate_mac_p.h \
- kernel/qeventdispatcher_mac_p.h
-
- MENU_NIB.files = mac/qt_menu.nib
- MENU_NIB.path = Resources
- MENU_NIB.version = Versions
- QMAKE_BUNDLE_DATA += MENU_NIB
- RESOURCES += mac/macresources.qrc
-
- LIBS_PRIVATE += -framework AppKit
+macx: {
+ HEADERS += kernel/qmacgesturerecognizer_p.h
+ SOURCES += kernel/qmacgesturerecognizer.cpp
}
wince*: {
diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h
index c041af7317..ae203d2819 100644
--- a/src/widgets/kernel/qgesture_p.h
+++ b/src/widgets/kernel/qgesture_p.h
@@ -190,41 +190,6 @@ public:
static int Timeout;
};
-#ifndef QT_NO_GESTURES
-class QNativeGestureEvent : public QEvent
-{
-public:
- enum Type {
- None,
- GestureBegin,
- GestureEnd,
- Pan,
- Zoom,
- Rotate,
- Swipe
- };
-
- QNativeGestureEvent()
- : QEvent(QEvent::NativeGesture), gestureType(None), percentage(0)
-#ifdef Q_WS_WIN
- , sequenceId(0), argument(0)
-#endif
- {
- }
-
- Type gestureType;
- float percentage;
- QPoint position;
- float angle;
-#ifdef Q_WS_WIN
- ulong sequenceId;
- quint64 argument;
-#endif
-};
-
-#endif // QT_NO_GESTURES
-
-
QT_END_NAMESPACE
#endif // QT_NO_GESTURES
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index d90b187bf0..6a0ccacdaa 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -51,8 +51,8 @@
#include "qevent.h"
#include "qgraphicsitem.h"
-#ifdef Q_WS_MAC
-#include "qmacgesturerecognizer_mac_p.h"
+#ifdef Q_OS_MAC
+#include "qmacgesturerecognizer_p.h"
#endif
#if defined(Q_WS_WIN) && !defined(QT_NO_NATIVE_GESTURES)
#include "qwinnativepangesturerecognizer_win_p.h"
@@ -76,7 +76,7 @@ QGestureManager::QGestureManager(QObject *parent)
{
qRegisterMetaType<Qt::GestureState>();
-#if defined(Q_WS_MAC)
+#if defined(Q_OS_MAC)
registerGestureRecognizer(new QMacSwipeGestureRecognizer);
registerGestureRecognizer(new QMacPinchGestureRecognizer);
registerGestureRecognizer(new QMacPanGestureRecognizer);
diff --git a/src/widgets/kernel/qmacgesturerecognizer.cpp b/src/widgets/kernel/qmacgesturerecognizer.cpp
new file mode 100644
index 0000000000..feb779e53f
--- /dev/null
+++ b/src/widgets/kernel/qmacgesturerecognizer.cpp
@@ -0,0 +1,275 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmacgesturerecognizer_p.h"
+#include "qgesture.h"
+#include "qgesture_p.h"
+#include "qevent.h"
+#include "qwidget.h"
+#include "qdebug.h"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+QMacSwipeGestureRecognizer::QMacSwipeGestureRecognizer()
+{
+}
+
+QGesture *QMacSwipeGestureRecognizer::create(QObject * /*target*/)
+{
+ return new QSwipeGesture;
+}
+
+QGestureRecognizer::Result
+QMacSwipeGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::NativeGesture && obj->isWidgetType()) {
+ QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
+ switch (ev->gestureType()) {
+ case Qt::SwipeNativeGesture: {
+ QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture);
+ g->setSwipeAngle(ev->value());
+ g->setHotSpot(ev->screenPos());
+ return QGestureRecognizer::FinishGesture | 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::create(QObject * /*target*/)
+{
+ return new QPinchGesture;
+}
+
+QGestureRecognizer::Result
+QMacPinchGestureRecognizer::recognize(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 Qt::BeginNativeGesture:
+ reset(gesture);
+ g->setStartCenterPoint(static_cast<QWidget*>(obj)->mapFromGlobal(ev->screenPos().toPoint()));
+ g->setCenterPoint(g->startCenterPoint());
+ g->setChangeFlags(QPinchGesture::CenterPointChanged);
+ g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags());
+ g->setHotSpot(ev->screenPos());
+ return QGestureRecognizer::MayBeGesture | QGestureRecognizer::ConsumeEventHint;
+ case Qt::RotateNativeGesture:
+ g->setLastScaleFactor(g->scaleFactor());
+ g->setLastRotationAngle(g->rotationAngle());
+ g->setRotationAngle(g->rotationAngle() + ev->value());
+ g->setChangeFlags(QPinchGesture::RotationAngleChanged);
+ g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags());
+ g->setHotSpot(ev->screenPos());
+ return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint;
+ case Qt::ZoomNativeGesture:
+ g->setLastScaleFactor(g->scaleFactor());
+ g->setLastRotationAngle(g->rotationAngle());
+ g->setScaleFactor(g->scaleFactor() * (1 + ev->value()));
+ g->setChangeFlags(QPinchGesture::ScaleFactorChanged);
+ g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags());
+ g->setHotSpot(ev->screenPos());
+ return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint;
+ case Qt::SmartZoomNativeGesture:
+ g->setLastScaleFactor(g->scaleFactor());
+ g->setLastRotationAngle(g->rotationAngle());
+ g->setScaleFactor(ev->value() ? 1.7f : 1.0f);
+ g->setChangeFlags(QPinchGesture::ScaleFactorChanged);
+ g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags());
+ g->setHotSpot(ev->screenPos());
+ return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint;
+ case Qt::EndNativeGesture:
+ return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint;
+ default:
+ break;
+ }
+ }
+
+ return QGestureRecognizer::Ignore;
+}
+
+void QMacPinchGestureRecognizer::reset(QGesture *gesture)
+{
+ QPinchGesture *g = static_cast<QPinchGesture *>(gesture);
+ g->setChangeFlags(0);
+ g->setTotalChangeFlags(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);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+QMacPanGestureRecognizer::QMacPanGestureRecognizer() : _panCanceled(true)
+{
+}
+
+QGesture *QMacPanGestureRecognizer::create(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::recognize(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();
+ _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::FinishGesture;
+ 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::CancelGesture;
+ }
+ } else {
+ const QPointF p = QCursor::pos();
+ const QPointF posOffset = p - _startPos;
+ g->setLastOffset(g->offset());
+ g->setOffset(QPointF(posOffset.x(), posOffset.y()));
+ g->setHotSpot(_startPos);
+ return QGestureRecognizer::TriggerGesture;
+ }
+ } 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::CancelGesture;
+ }
+ 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();
+ g->setHotSpot(_startPos);
+ return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint;
+ }
+ break; }
+ default:
+ break;
+ }
+
+ return QGestureRecognizer::Ignore;
+}
+
+void QMacPanGestureRecognizer::reset(QGesture *gesture)
+{
+ QPanGesture *g = static_cast<QPanGesture *>(gesture);
+ _startPos = QPointF();
+ _panCanceled = true;
+ g->setOffset(QPointF(0, 0));
+ g->setLastOffset(QPointF(0, 0));
+ g->setAcceleration(qreal(1));
+ QGestureRecognizer::reset(gesture);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
diff --git a/src/widgets/kernel/qmacgesturerecognizer_p.h b/src/widgets/kernel/qmacgesturerecognizer_p.h
new file mode 100644
index 0000000000..02f836b3f7
--- /dev/null
+++ b/src/widgets/kernel/qmacgesturerecognizer_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, 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.
+**
+**
+** $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"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+class QMacSwipeGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QMacSwipeGestureRecognizer();
+
+ QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event);
+ void reset(QGesture *gesture);
+};
+
+class QMacPinchGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QMacPinchGestureRecognizer();
+
+ QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event);
+ void reset(QGesture *gesture);
+};
+
+class QMacPanGestureRecognizer : public QObject, public QGestureRecognizer
+{
+public:
+ QMacPanGestureRecognizer();
+
+ QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event);
+ void reset(QGesture *gesture);
+private:
+ QPointF _startPos;
+ QBasicTimer _panTimer;
+ bool _panCanceled;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
+
+#endif // QMACSWIPEGESTURERECOGNIZER_MAC_P_H
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index f2bd389769..668d5b0fc0 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -49,6 +49,7 @@
#endif
#include <private/qwidgetbackingstore_p.h>
#include <qpa/qwindowsysteminterface_p.h>
+#include <private/qgesturemanager_p.h>
QT_BEGIN_NAMESPACE
@@ -220,6 +221,13 @@ bool QWidgetWindow::event(QEvent *event)
handleTabletEvent(static_cast<QTabletEvent *>(event));
return true;
#endif
+
+#ifndef QT_NO_GESTURES
+ case QEvent::NativeGesture:
+ handleGestureEvent(static_cast<QNativeGestureEvent *>(event));
+ return true;
+#endif
+
#ifndef QT_NO_CONTEXTMENU
case QEvent::ContextMenu:
handleContextMenuEvent(static_cast<QContextMenuEvent *>(event));
@@ -732,6 +740,25 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
}
#endif // QT_NO_TABLETEVENT
+#ifndef QT_NO_GESTURES
+void QWidgetWindow::handleGestureEvent(QNativeGestureEvent *e)
+{
+ // copy-pasted code to find correct widget follows:
+ QObject *receiver = 0;
+ if (QApplicationPrivate::inPopupMode()) {
+ QWidget *popup = QApplication::activePopupWidget();
+ QWidget *popupFocusWidget = popup->focusWidget();
+ receiver = popupFocusWidget ? popupFocusWidget : popup;
+ }
+ if (!receiver)
+ receiver = QApplication::widgetAt(e->globalPos());
+ if (!receiver)
+ receiver = m_widget; // last resort
+
+ QApplication::sendSpontaneousEvent(receiver, e);
+}
+#endif // QT_NO_GESTURES
+
#ifndef QT_NO_CONTEXTMENU
void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e)
{
diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h
index cb7bef8f3e..341aaba0d5 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa_p.h
+++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h
@@ -91,6 +91,9 @@ protected:
#ifndef QT_NO_TABLETEVENT
void handleTabletEvent(QTabletEvent *);
#endif
+#ifndef QT_NO_GESTURES
+ void handleGestureEvent(QNativeGestureEvent *);
+#endif
#ifndef QT_NO_CONTEXTMENU
void handleContextMenuEvent(QContextMenuEvent *);
#endif