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>
This commit is contained in:
Morten Johan Sørvig 2013-10-02 08:52:26 +02:00 committed by The Qt Project
parent 73e3d2f6cb
commit fbfc8ffbf3
17 changed files with 733 additions and 92 deletions

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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 =

View File

@ -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,

View File

@ -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;

View File

@ -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
{

View File

@ -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*: {

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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