diff options
author | Olli Werwolff <qt-info@nokia.com> | 2011-04-18 09:18:34 +0200 |
---|---|---|
committer | Olli Werwolff <qt-info@nokia.com> | 2011-04-19 10:25:34 +0200 |
commit | 9e5ff42afb356f8a1c25d24ab17860df046e59fe (patch) | |
tree | 412aa3b711de3d03fd6186c882881571b92de296 /src | |
parent | d4408b4009688c8fb3e006290c3851a86557cf09 (diff) |
Added multipoint touch support
Reviewed-by: ckamm
Task-number: QTSIM-77
Diffstat (limited to 'src')
-rw-r--r-- | src/other/inputfilter.cpp | 121 | ||||
-rw-r--r-- | src/other/inputfilter.h | 60 | ||||
-rw-r--r-- | src/other/mouseindicator.cpp | 83 | ||||
-rw-r--r-- | src/other/mouseindicator.h | 59 | ||||
-rw-r--r-- | src/other/other.pri | 15 | ||||
-rw-r--r-- | src/other/panmodefilter.cpp | 129 | ||||
-rw-r--r-- | src/other/panmodefilter.h | 59 | ||||
-rw-r--r-- | src/other/pinchmodefilter.cpp | 129 | ||||
-rw-r--r-- | src/other/pinchmodefilter.h | 59 | ||||
-rw-r--r-- | src/other/swipemodefilter.cpp | 158 | ||||
-rw-r--r-- | src/other/swipemodefilter.h | 62 | ||||
-rw-r--r-- | src/other/widget.cpp | 137 | ||||
-rw-r--r-- | src/other/widget.h | 15 | ||||
-rw-r--r-- | src/other/widgetmanager.cpp | 139 | ||||
-rw-r--r-- | src/other/widgetmanager.h | 34 | ||||
-rw-r--r-- | src/ui/inputscriptinterface.cpp | 27 | ||||
-rw-r--r-- | src/ui/inputscriptinterface.h | 13 | ||||
-rw-r--r-- | src/ui/mainwindow.cpp | 27 | ||||
-rw-r--r-- | src/ui/mainwindow.h | 6 | ||||
-rw-r--r-- | src/ui/multipointtouchui.cpp | 157 | ||||
-rw-r--r-- | src/ui/multipointtouchui.h | 89 | ||||
-rw-r--r-- | src/ui/ui.pri | 2 |
22 files changed, 1556 insertions, 24 deletions
diff --git a/src/other/inputfilter.cpp b/src/other/inputfilter.cpp new file mode 100644 index 0000000..c36aaa6 --- /dev/null +++ b/src/other/inputfilter.cpp @@ -0,0 +1,121 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#include "inputfilter.h" +#include "mouseindicator.h" +#include "qsimulatordata_p.h" +#include "widget.h" +#include "displaywidget.h" +#include "application.h" + +#include <QtGui/QGraphicsSceneEvent> + +InputFilter::InputFilter(QGraphicsItem *parent) + : QGraphicsItem(parent) +{ +} + +InputFilter::~InputFilter() +{ + removeValuePoints(); +} + +QRectF InputFilter::boundingRect() const +{ + return QRectF(); +} + +void InputFilter::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(painter) + Q_UNUSED(option) + Q_UNUSED(widget) +} + +QtSimulatorPrivate::TouchEventData InputFilter::createTouchEventFromMouseEvent(Widget *widget, + QGraphicsSceneMouseEvent *mouseEvent) +{ + DisplayWidget *display = widget->owner->display(); + QtSimulatorPrivate::TouchEventData touchEvent; + switch (mouseEvent->type()) { + case QEvent::GraphicsSceneMousePress: + touchEvent.type = static_cast<int>(QEvent::TouchBegin); + touchEvent.touchPointStates = Qt::TouchPointPressed; + break; + case QEvent::GraphicsSceneMouseMove: + touchEvent.type = static_cast<int>(QEvent::TouchUpdate); + touchEvent.touchPointStates = Qt::TouchPointMoved; + break; + case QEvent::GraphicsSceneMouseRelease: + touchEvent.type = static_cast<int>(QEvent::TouchEnd); + touchEvent.touchPointStates = Qt::TouchPointReleased; + break; + } + touchEvent.deviceType = QTouchEvent::TouchScreen; + touchEvent.modifiers = Qt::NoModifier; + QList<QtSimulatorPrivate::TouchPointData> touchPointList; + int id = 0; + foreach (const MouseIndicator *valuePoint, mValuePoints) { + QtSimulatorPrivate::TouchPointData touchPoint; + QSizeF size = valuePoint->rect().size(); + touchPoint.id = ++id; + touchPoint.rect = QRectF(valuePoint->center(), size); + touchPoint.sceneRect = QRectF(widget->mapToScene(valuePoint->center()), size); + touchPoint.screenRect = QRectF(widget->mapToItem(display, valuePoint->center()), size); + touchPoint.normalizedPos = QPointF(touchPoint.screenRect.center().x() / display->width(), + touchPoint.screenRect.center().y() / display->height()); + touchPoint.startPos = valuePoint->startPos(); + touchPoint.startScenePos = widget->mapToScene(valuePoint->startPos()); + touchPoint.startScreenPos = widget->mapToItem(display, valuePoint->startPos()); + touchPoint.startNormalizedPos = QPointF(touchPoint.startScreenPos.x() / display->width(), + touchPoint.startScreenPos.y() / display->height()); + touchPoint.lastPos = valuePoint->lastCenter(); + touchPoint.lastScenePos = widget->mapToScene(valuePoint->lastCenter()); + touchPoint.lastScreenPos = widget->mapToItem(display, valuePoint->lastCenter()); + touchPoint.lastNormalizedPos = QPointF(touchPoint.lastScreenPos.x() / display->width(), + touchPoint.lastScreenPos.y() / display->height()); + touchPoint.pressure = .75; + touchPointList.append(touchPoint); + } + touchEvent.touchPoints = touchPointList; + return touchEvent; +} + +void InputFilter::removeValuePoints() +{ + while (!mValuePoints.isEmpty()) { + MouseIndicator *valuePoint = mValuePoints.takeFirst(); + delete valuePoint; + valuePoint = 0; + } +} diff --git a/src/other/inputfilter.h b/src/other/inputfilter.h new file mode 100644 index 0000000..6be1a2f --- /dev/null +++ b/src/other/inputfilter.h @@ -0,0 +1,60 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#ifndef INPUTFILTER_H +#define INPUTFILTER_H + +#include "qsimulatordata_p.h" +#include <QGraphicsItem> + +class Widget; +class QGraphicsSceneMouseEvent; +class MouseIndicator; +class InputFilter : public QGraphicsItem +{ +public: + InputFilter(QGraphicsItem *parent = 0); + ~InputFilter(); + +protected: + virtual QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + QList<MouseIndicator *> mValuePoints; + + QtSimulatorPrivate::TouchEventData createTouchEventFromMouseEvent(Widget *widget, + QGraphicsSceneMouseEvent *mouseEvent); + void removeValuePoints(); +}; + +#endif // INPUTFILTER_H diff --git a/src/other/mouseindicator.cpp b/src/other/mouseindicator.cpp new file mode 100644 index 0000000..3956e86 --- /dev/null +++ b/src/other/mouseindicator.cpp @@ -0,0 +1,83 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#include "mouseindicator.h" + +#include <QtGui/QBrush> + +MouseIndicator::MouseIndicator(QGraphicsItem *parent) + : QGraphicsEllipseItem(parent) +{ +} + +MouseIndicator::MouseIndicator(qreal x, qreal y, QGraphicsItem *parent) + : QGraphicsEllipseItem(0, 0, 15, 15, parent) +{ + setCenter(QPointF(x, y)); + setBrush(Qt::gray); +} + +MouseIndicator::MouseIndicator(QPointF center, QGraphicsItem *parent) + : QGraphicsEllipseItem(0, 0, 15, 15, parent) +{ + setCenter(center); + setBrush(Qt::gray); +} + +MouseIndicator::~MouseIndicator() +{ +} + +QPointF MouseIndicator::center() const +{ + return pos() + QPointF(rect().width(), rect().height()) / 2; +} + +void MouseIndicator::setCenter(const QPointF &newCenter) +{ + mLastCenter = center(); + setPos(newCenter - QPointF(rect().width(), rect().height()) / 2); +} + +QPointF MouseIndicator::startPos() const +{ + return mStartPosition; +} + +void MouseIndicator::setStartPos(const QPointF &startPos) +{ + mLastCenter = startPos; + mStartPosition = startPos; +} + + diff --git a/src/other/mouseindicator.h b/src/other/mouseindicator.h new file mode 100644 index 0000000..59aeb51 --- /dev/null +++ b/src/other/mouseindicator.h @@ -0,0 +1,59 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#ifndef MOUSEINDICATOR_H +#define MOUSEINDICATOR_H + +#include <QtGui/QGraphicsEllipseItem> + +class MouseIndicator : public QGraphicsEllipseItem +{ +public: + MouseIndicator(QGraphicsItem *parent = 0); + MouseIndicator(qreal centerX, qreal centerY, QGraphicsItem *parent = 0); + MouseIndicator(QPointF center, QGraphicsItem *parent = 0); + virtual ~MouseIndicator(); + + QPointF center() const; + void setCenter(const QPointF &newCenter); + QPointF lastCenter() const { return mLastCenter; } + + QPointF startPos() const; + void setStartPos(const QPointF &startPos); + +private: + QPointF mStartPosition; + QPointF mLastCenter; +}; + +#endif // MOUSEINDICATOR_H diff --git a/src/other/other.pri b/src/other/other.pri index b83c43c..45f2619 100644 --- a/src/other/other.pri +++ b/src/other/other.pri @@ -9,7 +9,13 @@ SOURCES += application.cpp \ displaywidget.cpp \ phononmanager.cpp \ widgetmanager.cpp \ - widget.cpp + widget.cpp \ + mouseindicator.cpp \ + inputfilter.cpp \ + pinchmodefilter.cpp \ + panmodefilter.cpp \ + swipemodefilter.cpp + HEADERS += application.h \ applicationmanager.h \ configurationreader.h \ @@ -17,7 +23,12 @@ HEADERS += application.h \ displaywidget.h \ phononmanager.h \ widgetmanager.h \ - widget.h + widget.h \ + mouseindicator.h \ + inputfilter.h \ + pinchmodefilter.h \ + panmodefilter.h \ + swipemodefilter.h contains(QT_CONFIG, phonon) { SOURCES += \ diff --git a/src/other/panmodefilter.cpp b/src/other/panmodefilter.cpp new file mode 100644 index 0000000..7be37f7 --- /dev/null +++ b/src/other/panmodefilter.cpp @@ -0,0 +1,129 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#include "panmodefilter.h" +#include "mouseindicator.h" +#include "widget.h" +#include "application.h" + +#include <QtGui/QGraphicsSceneEvent> + +PanModeFilter::PanModeFilter(QGraphicsItem *parent) + : InputFilter(parent) + , mState(setFirstPoint) +{ +} + +PanModeFilter::~PanModeFilter() +{ +} + +bool PanModeFilter::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + Widget *widget = static_cast<Widget *>(watched); + QGraphicsSceneMouseEvent *ev = 0; + switch (event->type()) { + case QEvent::GraphicsSceneMousePress: + ev = static_cast<QGraphicsSceneMouseEvent *>(event); + switch (mState) { + case setFirstPoint: + mState = updateFirstPoint; + mValuePoints.append(new MouseIndicator(ev->pos(), widget)); + mValuePoints[0]->setBrush(Qt::red); + return true; + case setSecondPoint: + if (mValuePoints[0]->contains(mapToItem(mValuePoints[0], ev->pos()))) { + mState = updateFirstPoint; + if (mValuePoints.length() == 2) + mValuePoints[1]->setVisible(false); + } else { + if (mValuePoints.length() == 1) { + mValuePoints.append(new MouseIndicator(ev->pos(), this)); + } else { + mValuePoints[1]->setCenter(ev->pos()); + mValuePoints[1]->setVisible(true); + } + mPanDiff = ev->pos() - mValuePoints[0]->center(); + mValuePoints[0]->setStartPos(mValuePoints[0]->center()); + mValuePoints[1]->setStartPos(mValuePoints[1]->center()); + mState = updateSecondPoint; + QtSimulatorPrivate::TouchEventData touchEvent = createTouchEventFromMouseEvent(widget, ev); + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + touchEvent); + } + return true; + } + break; + case QEvent::GraphicsSceneMouseRelease: + ev = static_cast<QGraphicsSceneMouseEvent *>(event); + switch (mState) { + case updateFirstPoint: + mState = setSecondPoint; + return true; + case updateSecondPoint: + QtSimulatorPrivate::TouchEventData touchEvent = createTouchEventFromMouseEvent(widget, ev); + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + touchEvent); + mState = setSecondPoint; + return true; + } + break; + case QEvent::GraphicsSceneMouseMove: + ev = static_cast<QGraphicsSceneMouseEvent *>(event); + switch (mState) { + case updateFirstPoint: + mValuePoints[0]->setCenter(ev->pos()); + return true; + case updateSecondPoint: + mValuePoints[1]->setCenter(ev->pos()); + mValuePoints[0]->setCenter(mValuePoints[1]->center() - mPanDiff); + QtSimulatorPrivate::TouchEventData touchEvent = createTouchEventFromMouseEvent(widget, ev); + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + touchEvent); + return true; + } + break; + default: + break; + } + return false; +} diff --git a/src/other/panmodefilter.h b/src/other/panmodefilter.h new file mode 100644 index 0000000..c21de7e --- /dev/null +++ b/src/other/panmodefilter.h @@ -0,0 +1,59 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#ifndef PANMODEFILTER_H +#define PANMODEFILTER_H + +#include "inputfilter.h" + +class QPointF; +class PanModeFilter : public InputFilter +{ +public: + PanModeFilter(QGraphicsItem *parent = 0); + ~PanModeFilter(); + +protected: + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); + +private: + QPointF mPanDiff; + enum FilterState { + setFirstPoint, + updateFirstPoint, + setSecondPoint, + updateSecondPoint + } mState; +}; + +#endif // PANMODEFILTER_H diff --git a/src/other/pinchmodefilter.cpp b/src/other/pinchmodefilter.cpp new file mode 100644 index 0000000..b4061dc --- /dev/null +++ b/src/other/pinchmodefilter.cpp @@ -0,0 +1,129 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#include "pinchmodefilter.h" +#include "mouseindicator.h" +#include "widget.h" +#include "application.h" + +#include <QtGui/QGraphicsSceneEvent> + +PinchModeFilter::PinchModeFilter(QGraphicsItem *parent) + : InputFilter(parent) + , mState(setReferencePoint) +{ + mReferencePoint = new MouseIndicator(0, 0, this); + mReferencePoint->setVisible(false); + mReferencePoint->setBrush(Qt::red); + mReferencePoint->setCursor(Qt::OpenHandCursor); +} + +PinchModeFilter::~PinchModeFilter() +{ +} + +bool PinchModeFilter::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + Widget *widget = static_cast<Widget *>(watched); + QGraphicsSceneMouseEvent *ev = 0; + switch (event->type()) { + case QEvent::GraphicsSceneMousePress: + ev = static_cast<QGraphicsSceneMouseEvent *>(event); + switch (mState) { + case setReferencePoint: + mState = updateReferencePoint; + mReferencePoint->setCenter(ev->pos()); + mReferencePoint->setVisible(true); + return true; + case setTouchPoints: + removeValuePoints(); + if (mReferencePoint->contains(mapToItem(mReferencePoint, ev->pos()))) { + mState = updateReferencePoint; + } else { + mValuePoints.append(new MouseIndicator(ev->pos(), widget)); + mValuePoints[0]->setStartPos(mValuePoints[0]->center()); + QPointF diff = ev->pos() - mReferencePoint->center(); + mValuePoints.append(new MouseIndicator(mReferencePoint->center() - diff, widget)); + mValuePoints[1]->setStartPos(mValuePoints[1]->center()); + mState = updateTouchPoints; + QtSimulatorPrivate::TouchEventData touchEvent = createTouchEventFromMouseEvent(widget, ev); + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + touchEvent); + } + return true; + } + break; + case QEvent::GraphicsSceneMouseRelease: + ev = static_cast<QGraphicsSceneMouseEvent *>(event); + switch (mState) { + case updateReferencePoint: + mState = setTouchPoints; + return true; + case updateTouchPoints: + QtSimulatorPrivate::TouchEventData touchEvent = createTouchEventFromMouseEvent(widget, ev); + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + touchEvent); + mState = setTouchPoints; + return true; + } + break; + case QEvent::GraphicsSceneMouseMove: + ev = static_cast<QGraphicsSceneMouseEvent *>(event); + switch (mState) { + case updateReferencePoint: + mReferencePoint->setCenter(ev->pos()); + return true; + case updateTouchPoints: + mValuePoints[0]->setCenter(ev->pos()); + QPointF diff = ev->pos() - mReferencePoint->center(); + mValuePoints[1]->setCenter(mReferencePoint->center() - diff); + QtSimulatorPrivate::TouchEventData touchEvent = createTouchEventFromMouseEvent(widget, ev); + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + touchEvent); + return true; + } + break; + default: + break; + } + return false; +} diff --git a/src/other/pinchmodefilter.h b/src/other/pinchmodefilter.h new file mode 100644 index 0000000..ff3544b --- /dev/null +++ b/src/other/pinchmodefilter.h @@ -0,0 +1,59 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#ifndef PINCHMODEFILTER_H +#define PINCHMODEFILTER_H + +#include "inputfilter.h" + +class PinchModeFilter : public InputFilter +{ +public: + PinchModeFilter(QGraphicsItem *parent = 0); + ~PinchModeFilter(); + +protected: + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); + +private: + MouseIndicator *mReferencePoint; + + enum FilterState { + setReferencePoint, + updateReferencePoint, + setTouchPoints, + updateTouchPoints + } mState; +}; + +#endif // PINCHMODEFILTER_H diff --git a/src/other/swipemodefilter.cpp b/src/other/swipemodefilter.cpp new file mode 100644 index 0000000..dbc3ae2 --- /dev/null +++ b/src/other/swipemodefilter.cpp @@ -0,0 +1,158 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#include "swipemodefilter.h" +#include "mouseindicator.h" +#include "widget.h" +#include "application.h" + +#include <QtGui/QGraphicsSceneEvent> + +SwipeModeFilter::SwipeModeFilter(QGraphicsItem *parent) + : InputFilter(parent) + , mState(setFirstPoint) +{ +} + +SwipeModeFilter::~SwipeModeFilter() +{ +} + +bool SwipeModeFilter::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + Widget *widget = static_cast<Widget *>(watched); + QGraphicsSceneMouseEvent *ev = 0; + switch (event->type()) { + case QEvent::GraphicsSceneMousePress: + ev = static_cast<QGraphicsSceneMouseEvent *>(event); + switch (mState) { + case setFirstPoint: + mState = updateFirstPoint; + mValuePoints.append(new MouseIndicator(ev->pos(), this)); + mValuePoints.last()->setBrush(Qt::red); + return true; + case setSecondPoint: + if (mValuePoints[0]->contains(mapToItem(mValuePoints[0], ev->pos()))) { + mState = updateFirstPoint; + if (mValuePoints.length() == 3) + mValuePoints[2]->setVisible(false); + } else { + mState = updateSecondPoint; + mValuePoints.append(new MouseIndicator(ev->pos(), this)); + mValuePoints.last()->setBrush(Qt::red); + } + return true; + break; + case setThirdPoint: + if (mValuePoints[0]->contains(mapToItem(mValuePoints[0], ev->pos()))) { + mState = updateFirstPoint; + if (mValuePoints.length() == 3) + mValuePoints[2]->setVisible(false); + } else if (mValuePoints[1]->contains(mapToItem(mValuePoints[1], ev->pos()))) { + mState = updateSecondPoint; + if (mValuePoints.length() == 3) + mValuePoints[2]->setVisible(false); + } else { + if (mValuePoints.length() == 2) { + mValuePoints.append(new MouseIndicator(ev->pos(), this)); + } else { + mValuePoints[2]->setCenter(ev->pos()); + mValuePoints[2]->setVisible(true); + } + mDiff1 = ev->pos() - mValuePoints[0]->center(); + mDiff2 = ev->pos() - mValuePoints[1]->center(); + mValuePoints[0]->setStartPos(mValuePoints[0]->center()); + mValuePoints[1]->setStartPos(mValuePoints[1]->center()); + mValuePoints[2]->setStartPos(mValuePoints[2]->center()); + mState = updateThirdPoint; + QtSimulatorPrivate::TouchEventData touchEvent = createTouchEventFromMouseEvent(widget, ev); + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + touchEvent); + } + return true; + } + break; + case QEvent::GraphicsSceneMouseRelease: + ev = static_cast<QGraphicsSceneMouseEvent *>(event); + switch (mState) { + case updateFirstPoint: + if (mValuePoints.length() == 1) + mState = setSecondPoint; + else + mState = setThirdPoint; + return true; + case updateSecondPoint: + mState = setThirdPoint; + return true; + case 5: + QtSimulatorPrivate::TouchEventData touchEvent = createTouchEventFromMouseEvent(widget, ev); + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + touchEvent); + mState = updateThirdPoint; + return true; + } + break; + case QEvent::GraphicsSceneMouseMove: + ev = static_cast<QGraphicsSceneMouseEvent *>(event); + switch (mState) { + case updateFirstPoint: + mValuePoints[0]->setCenter(ev->pos()); + return true; + case updateSecondPoint: + mValuePoints[1]->setCenter(ev->pos()); + return true; + case updateThirdPoint: + mValuePoints[2]->setCenter(ev->pos()); + mValuePoints[1]->setCenter(mValuePoints[2]->center() - mDiff1); + mValuePoints[0]->setCenter(mValuePoints[2]->center() - mDiff2); + QtSimulatorPrivate::TouchEventData touchEvent = createTouchEventFromMouseEvent(widget, ev); + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + touchEvent); + return true; + } + break; + + default: + break; + } + return false; +} diff --git a/src/other/swipemodefilter.h b/src/other/swipemodefilter.h new file mode 100644 index 0000000..9e4a956 --- /dev/null +++ b/src/other/swipemodefilter.h @@ -0,0 +1,62 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#ifndef SWIPEMODEFILTER_H +#define SWIPEMODEFILTER_H + +#include "inputfilter.h" + +class QPointF; +class SwipeModeFilter : public InputFilter +{ +public: + SwipeModeFilter(QGraphicsItem *parent = 0); + ~SwipeModeFilter(); + +protected: + virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); + +private: + QPointF mDiff1; + QPointF mDiff2; + enum FilterState { + setFirstPoint, + updateFirstPoint, + setSecondPoint, + updateSecondPoint, + setThirdPoint, + updateThirdPoint + } mState; +}; + +#endif // SWIPEMODEFILTER_H diff --git a/src/other/widget.cpp b/src/other/widget.cpp index e573252..dd60275 100644 --- a/src/other/widget.cpp +++ b/src/other/widget.cpp @@ -36,6 +36,11 @@ #include "application.h" #include "displaywidget.h" #include "qsimulatordata_p.h" +#include "mouseindicator.h" +#include "widgetmanager.h" +#include "pinchmodefilter.h" +#include "panmodefilter.h" +#include "swipemodefilter.h" #ifndef QT_NO_PHONON #include "phononvideowidget.h" @@ -48,6 +53,7 @@ #include <QtGui/QPainter> #include <QtGui/QGraphicsSceneMouseEvent> #include <QtGui/QGraphicsScene> +#include <QtGui/QTouchEvent> class Sleeper : QThread { @@ -68,6 +74,7 @@ Widget::Widget(QRect geometry, QImage::Format f, const QString &t, Application* , widgetId(id) , title(t) , owner(who) + , mManager(0) , memory(0) , width(geometry.width()) , height(geometry.height()) @@ -78,6 +85,8 @@ Widget::Widget(QRect geometry, QImage::Format f, const QString &t, Application* , mMaemo5Stacked(false) , mOrientation(Qt::WA_AutoOrientation) , mSharedMemoryName(sharedMemoryName) + , mMouseInputMode(MultiPointTouchUi::defaultMode) + , mFilterItem(0) { //Commented out, in order to be //able to easily re-enable mouse tracking @@ -186,35 +195,58 @@ void Widget::setGeometry(QRect g) void Widget::mousePressEvent(QGraphicsSceneMouseEvent* ev) { - handleMouseEvent(QEvent::MouseButtonPress, ev); + switch (mMouseInputMode) { + case MultiPointTouchUi::defaultMode: + handleMouseEvent(QEvent::MouseButtonPress, ev); + break; + case MultiPointTouchUi::freeMode: + mManager->runCurrentGestureScript(); + break; + } } void Widget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev) { - handleMouseEvent(QEvent::MouseButtonDblClick, ev); + switch (mMouseInputMode) { + case MultiPointTouchUi::defaultMode: + handleMouseEvent(QEvent::MouseButtonDblClick, ev); + break; + } } void Widget::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev) { - handleMouseEvent(QEvent::MouseButtonRelease, ev); + switch (mMouseInputMode) { + case MultiPointTouchUi::defaultMode: + handleMouseEvent(QEvent::MouseButtonRelease, ev); + break; + } } void Widget::mouseMoveEvent(QGraphicsSceneMouseEvent* ev) { - handleMouseEvent(QEvent::MouseMove, ev); + switch (mMouseInputMode) { + case MultiPointTouchUi::defaultMode: + handleMouseEvent(QEvent::MouseMove, ev); + break; + } } void Widget::hoverMoveEvent(QGraphicsSceneHoverEvent *ev) { - QtSimulatorPrivate::RemoteMetacall<void>::call(owner->socket(), QtSimulatorPrivate::NoSync, - "dispatchMouseEvent", - widgetId, - static_cast<int>(QEvent::MouseMove), - mapToItem(owner->display(), ev->pos() - offset).toPoint(), - static_cast<int>(Qt::NoButton), - static_cast<int>(Qt::NoButton), - static_cast<int>(ev->modifiers())); - ev->accept(); + switch (mMouseInputMode) { + case MultiPointTouchUi::defaultMode: + QtSimulatorPrivate::RemoteMetacall<void>::call(owner->socket(), QtSimulatorPrivate::NoSync, + "dispatchMouseEvent", + widgetId, + static_cast<int>(QEvent::MouseMove), + mapToItem(owner->display(), ev->pos() - offset).toPoint(), + static_cast<int>(Qt::NoButton), + static_cast<int>(Qt::NoButton), + static_cast<int>(ev->modifiers())); + ev->accept(); + break; + } } void Widget::handleMouseEvent(QEvent::Type type, QGraphicsSceneMouseEvent *ev) @@ -225,13 +257,13 @@ void Widget::handleMouseEvent(QEvent::Type type, QGraphicsSceneMouseEvent *ev) } QtSimulatorPrivate::RemoteMetacall<void>::call(owner->socket(), QtSimulatorPrivate::NoSync, - "dispatchMouseEvent", - widgetId, - static_cast<int>(type), - mapToItem(owner->display(), ev->pos() - offset).toPoint(), - static_cast<int>(ev->button()), - static_cast<int>(ev->buttons()), - static_cast<int>(ev->modifiers())); + "dispatchMouseEvent", + widgetId, + static_cast<int>(type), + mapToItem(owner->display(), ev->pos() - offset).toPoint(), + static_cast<int>(ev->button()), + static_cast<int>(ev->buttons()), + static_cast<int>(ev->modifiers())); ev->accept(); } @@ -264,6 +296,46 @@ void Widget::handleKeyEvent(QKeyEvent* ev) ev->accept(); } +void Widget::event(QEvent *e) +{ + if (e->type() == QEvent::TouchBegin + || e->type() == QEvent::TouchUpdate + || e->type() == QEvent::TouchEnd) { + QTouchEvent *ev = static_cast<QTouchEvent *>(e); + QtSimulatorPrivate::TouchEventData touchEventData; + touchEventData.type = static_cast<int>(ev->type()); + touchEventData.deviceType = static_cast<int>(ev->deviceType()); + touchEventData.modifiers = static_cast<int>(ev->modifiers()); + touchEventData.touchPointStates = static_cast<int>(ev->touchPointStates()); + foreach (const QTouchEvent::TouchPoint &tp, ev->touchPoints()) { + QtSimulatorPrivate::TouchPointData touchPoint; + touchPoint.id = tp.id(); + touchPoint.state = tp.state(); + touchPoint.rect = tp.rect(); + touchPoint.sceneRect = tp.sceneRect(); + touchPoint.screenRect = tp.screenRect(); + touchPoint.normalizedPos = tp.normalizedPos(); + touchPoint.startPos = tp.startPos(); + touchPoint.startScenePos = tp.startScenePos(); + touchPoint.startScreenPos = tp.startScreenPos(); + touchPoint.startNormalizedPos = tp.startNormalizedPos(); + touchPoint.lastPos = tp.lastPos(); + touchPoint.lastScenePos = tp.lastScenePos(); + touchPoint.lastScreenPos = tp.lastScreenPos(); + touchPoint.lastNormalizedPos = tp.lastNormalizedPos(); + touchPoint.pressure = tp.pressure(); + touchEventData.touchPoints.append(touchPoint); + } + + QtSimulatorPrivate::RemoteMetacall<void>::call(owner->socket(), QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widgetId, + touchEventData); + ev->accept(); + } +} + + void Widget::updateOffset(const QPoint &newOffset) { if (offset != newOffset) { @@ -293,3 +365,28 @@ void Widget::setWidgetVisible(bool visible) mWidgetVisible = visible; update(); } + +void Widget::setMouseInputMode(MultiPointTouchUi::InputMode newMode) +{ + if (mFilterItem) { + removeSceneEventFilter(mFilterItem); + delete mFilterItem; + mFilterItem = 0; + } + switch (newMode) { + case MultiPointTouchUi::pinchMode: + mFilterItem = new PinchModeFilter(this); + installSceneEventFilter(mFilterItem); + break; + case MultiPointTouchUi::panMode: + mFilterItem = new PanModeFilter(this); + installSceneEventFilter(mFilterItem); + break; + case MultiPointTouchUi::swipeMode: + mFilterItem = new SwipeModeFilter(this); + installSceneEventFilter(mFilterItem); + break; + } + + mMouseInputMode = newMode; +} diff --git a/src/other/widget.h b/src/other/widget.h index 9633bbe..138efd0 100644 --- a/src/other/widget.h +++ b/src/other/widget.h @@ -34,6 +34,8 @@ #ifndef WIDGET_H #define WIDGET_H +#include "multipointtouchui.h" + #include <QtGui/QGraphicsItem> #include <QtGui/QtEvents> @@ -41,6 +43,11 @@ class Application; class QSharedMemory; class QString; class QMenuBar; +class MouseIndicator; +namespace QtSimulatorPrivate { +struct TouchEventData; +struct TouchPointData; +} class Widget : public QGraphicsItem { @@ -77,6 +84,7 @@ public: void setMaemo5Stacked(bool stacked) { mMaemo5Stacked = stacked; } Qt::WidgetAttribute orientation() { return mOrientation; } void setOrientation(Qt::WidgetAttribute orientation) { mOrientation = orientation; } + void setMouseInputMode(MultiPointTouchUi::InputMode newMode); protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent* ev); @@ -86,11 +94,13 @@ protected: virtual void hoverMoveEvent(QGraphicsSceneHoverEvent* ev); virtual void keyPressEvent(QKeyEvent* ev); virtual void keyReleaseEvent(QKeyEvent* ev); + virtual void event(QEvent* e); void handleMouseEvent(QEvent::Type type, QGraphicsSceneMouseEvent* ev); void handleKeyEvent(QKeyEvent* ev); private: friend class WidgetManager; + WidgetManager *mManager; friend class DisplayWidget; QSharedMemory *memory; @@ -107,6 +117,11 @@ private: // invisible parents bool mWidgetVisible; QString mSharedMemoryName; + + //Multipoint-touch + MultiPointTouchUi::InputMode mMouseInputMode; + + QGraphicsItem *mFilterItem; }; #endif // WIDGET_H diff --git a/src/other/widgetmanager.cpp b/src/other/widgetmanager.cpp index 01d50ac..c5da7c8 100644 --- a/src/other/widgetmanager.cpp +++ b/src/other/widgetmanager.cpp @@ -43,6 +43,7 @@ #include <QtGui/QWidget> #include <QtGui/QTableWidget> #include <QtGui/QLayout> +#include <QtGui/QGraphicsScene> namespace { int gWidgetIdCounter = 100; // 0 is the desktop. @@ -63,6 +64,7 @@ WidgetManager::WidgetManager(DisplayWidget *dw, QObject *parent) , mFocusWidget(0) , mSharedMemoryIndex(qrand()) , mSymbianSoftKeysSupported(false) + , mCurrentMouseInputMode(MultiPointTouchUi::defaultMode) { // Some client applications repaint themselves continuously and send an inordinate amount // of paint events. If we call update for every one of these, the event loop stalls on unix @@ -86,6 +88,7 @@ WidgetManager::WidgetManager(DisplayWidget *dw, QObject *parent) connect(this, SIGNAL(topWidgetChanged(Widget*)), this, SLOT(maybeFullscreen(Widget *))); connect(this, SIGNAL(topWidgetChanged(Widget*)), this, SLOT(updateMaemoNavigate(Widget*))); connect(this, SIGNAL(topWidgetChanged(Widget*)), this, SLOT(handleTopOrientation(Widget*))); + mScriptInterface = new TouchScriptInterface(this); } WidgetManager::~WidgetManager() @@ -177,8 +180,10 @@ QtSimulatorPrivate::NewWindowInfo WidgetManager::create( geometry.size()); Widget *w = new Widget(geometry, mImageFormat, title, app, gWidgetIdCounter++, sharedMemoryName, parent); + w->mManager = this; w->setWidgetVisible(false); w->offset = mOffset; + w->setMouseInputMode(mCurrentMouseInputMode); widgets.push_front(w); setHighestZ(w); @@ -418,6 +423,14 @@ void WidgetManager::setMaemo5StackedWindowFlag(int id, bool stacked) w->setMaemo5Stacked(stacked); } +void WidgetManager::setAcceptsTouchEvents(int id, bool accept) +{ + Widget *w = widgetForId(id); + if (!w) + return; + w->setAcceptsHoverEvents(accept); +} + void WidgetManager::handleUpdateRequests() { foreach (Widget *w, widgets) { @@ -691,3 +704,129 @@ void WidgetManager::handleTopOrientation(Widget *topWidget) else emit topOrientationChanged(topWidget->orientation()); } + +void WidgetManager::setMouseInputMode(MultiPointTouchUi::InputMode newMode) +{ + mCurrentMouseInputMode = newMode; + foreach (Widget* w, widgets) + w->setMouseInputMode(newMode); +} + +TouchScriptInterface::TouchScriptInterface(WidgetManager *wm) + : QObject(wm) + , mWidgetManager(wm) +{ +} + +TouchScriptInterface::~TouchScriptInterface() +{ +} + +QtSimulatorPrivate::TouchPointData TouchScriptInterface::updateTouchPoint(const QtSimulatorPrivate::TouchPointData &touchPoint, + QEvent::Type touchType, const QPointF ¢er, const QSizeF &size) +{ + QtSimulatorPrivate::TouchPointData newTouchPoint; + DisplayWidget *displayWidget = mWidgetManager->display(); + + switch (touchType) { + case QEvent::TouchBegin: + newTouchPoint.startPos = newTouchPoint.lastPos = center; + newTouchPoint.startScenePos = newTouchPoint.lastScenePos = displayWidget->mapToScene(center); + newTouchPoint.startScreenPos = newTouchPoint.lastScreenPos = displayWidget->mapToItem(displayWidget, center); + newTouchPoint.startNormalizedPos = newTouchPoint.lastNormalizedPos = QPointF(newTouchPoint.startScreenPos.x() / displayWidget->width(), + newTouchPoint.startScreenPos.y() / displayWidget->height()); + break; + case QEvent::TouchUpdate: + newTouchPoint.startPos = touchPoint.startPos; + newTouchPoint.startScenePos = touchPoint.startScenePos; + newTouchPoint.startScreenPos = touchPoint.startScreenPos; + newTouchPoint.startNormalizedPos = touchPoint.startNormalizedPos; + newTouchPoint.lastPos = touchPoint.rect.center(); + newTouchPoint.lastScenePos = displayWidget->mapToScene(touchPoint.rect.center()); + newTouchPoint.lastScreenPos = displayWidget->mapToItem(displayWidget, touchPoint.rect.center()); + newTouchPoint.lastNormalizedPos = QPointF(newTouchPoint.lastScreenPos.x() / displayWidget->width(), + newTouchPoint.lastScreenPos.y() / displayWidget->height()); + break; + default: + return touchPoint; + } + newTouchPoint.rect = QRectF(center - QPointF(size.width() / 2, size.height() / 2), size); + newTouchPoint.sceneRect = QRectF(displayWidget->mapToScene(center - QPointF(size.width() / 2, size.height() / 2)), size); + newTouchPoint.screenRect = QRectF(displayWidget->mapToItem(displayWidget, center - QPointF(size.width() / 2, size.height() / 2)), size); + newTouchPoint.normalizedPos = QPointF((newTouchPoint.screenRect.center().x() - size.width() / 2) / displayWidget->width(), + (newTouchPoint.screenRect.center().y() - size.height() / 2) / displayWidget->height()); + + newTouchPoint.pressure = .75; + return newTouchPoint; +} + +void TouchScriptInterface::beginTouch(int id, int x, int y) +{ + fireTouchEvent(id, x, y, QEvent::TouchBegin); +} + +void TouchScriptInterface::updateTouch(int id, int x, int y) +{ + fireTouchEvent(id, x, y, QEvent::TouchUpdate); +} + +void TouchScriptInterface::endTouch(int id, int x, int y) +{ + fireTouchEvent(id, x, y, QEvent::TouchEnd); +} + +void TouchScriptInterface::fireTouchEvent(int id, int x, int y, QEvent::Type type) +{ + Widget *widget = mWidgetManager->widgetForId(mWidgetManager->widgetAt(QPoint(x, y))); + if (!widget) + return; + QtSimulatorPrivate::TouchPointData point; + int i = 0; + bool found = false; + for (i; i < data.touchPoints.length(); ++i) { + if (data.touchPoints.at(i).id == id) { + found = true; + point = data.touchPoints.at(i); + break; + } + } + point = updateTouchPoint(point, type, QPointF(x, y), QSizeF(15, 15)); + point.id = id; + if (found) + data.touchPoints[i] = point; + else { + data.touchPoints.append(point); + } + data.type = static_cast<int>(type); + switch (type) { + case QEvent::TouchBegin: + data.touchPointStates = Qt::TouchPointPressed; + break; + case QEvent::TouchUpdate: + data.touchPointStates = Qt::TouchPointMoved; + break; + case QEvent::TouchEnd: + data.touchPointStates = Qt::TouchPointReleased; + data.touchPoints.takeAt(i); + break; + default: + break; + } + data.deviceType = QTouchEvent::TouchScreen; + data.modifiers = Qt::NoModifier; + QtSimulatorPrivate::RemoteMetacall<void>::call(widget->owner->socket(), + QtSimulatorPrivate::NoSync, + "dispatchTouchEvent", + widget->widgetId, + data); +} + +void WidgetManager::runCurrentGestureScript() +{ + emit gestureScriptRequested(mCurrentGesturePath); +} + +void WidgetManager::setCurrentGesturePath(const QString &path) +{ + mCurrentGesturePath = path; +} diff --git a/src/other/widgetmanager.h b/src/other/widgetmanager.h index fad056c..d0c892b 100644 --- a/src/other/widgetmanager.h +++ b/src/other/widgetmanager.h @@ -36,6 +36,7 @@ #include "deviceitem.h" #include "qsimulatordata_p.h" +#include "multipointtouchui.h" #include <QtGui/QImage> #include <QtCore/QObject> @@ -48,6 +49,27 @@ class QRect; class QTableWidget; class QWidget; class QMenuBar; +class WidgetManager; + +class TouchScriptInterface : public QObject { + Q_OBJECT +public: + TouchScriptInterface(WidgetManager *wm); + virtual ~TouchScriptInterface(); + + Q_INVOKABLE void beginTouch(int id, int x, int y); + Q_INVOKABLE void updateTouch(int id, int x, int y); + Q_INVOKABLE void endTouch(int id, int x, int y); + +private: + QtSimulatorPrivate::TouchPointData updateTouchPoint(const QtSimulatorPrivate::TouchPointData &touchPoint, + QEvent::Type touchType, const QPointF ¢er, + const QSizeF &size); + void fireTouchEvent(int id, int x, int y, QEvent::Type type); + + WidgetManager *mWidgetManager; + QtSimulatorPrivate::TouchEventData data; +}; class WidgetManager : public QObject { @@ -67,6 +89,7 @@ public: QtSimulatorPrivate::NewWindowInfo create( int parentWidgetId, QRect geometry, const QString &title, Application *app); + void runCurrentGestureScript(); public slots: int widgetAt(const QPoint &position) const; @@ -88,6 +111,7 @@ public slots: void setWidgetParent(int id, int newParentId); void setMaemo5StackedWindowFlag(int id, bool stacked); void setOrientationAttribute(int id, int orientation, bool on); + void setAcceptsTouchEvents(int id, bool accept); void onApplicationUnregistered(int appId); @@ -99,6 +123,10 @@ public slots: void changeOffset(const QPoint &offset); void updateSymbianSoftKeys(); + void setMouseInputMode(MultiPointTouchUi::InputMode newMode); + void setCurrentGesturePath(const QString &path); + + TouchScriptInterface *scriptInterface() const { return mScriptInterface; } private slots: void handleUpdateRequests(); @@ -111,6 +139,7 @@ signals: void topOrientationChanged(Qt::WidgetAttribute orientation); void symbianSoftKeyTextChanged(int buttonNr, QString text); void maemoNavigationChanged(MaemoNavigationMode mode); + void gestureScriptRequested(const QString &filePath); private: void updateLogItem(int id); @@ -129,6 +158,11 @@ private: QImage::Format mImageFormat; bool mSymbianSoftKeysSupported; + MultiPointTouchUi::InputMode mCurrentMouseInputMode; + + friend class TouchScriptInterface; + TouchScriptInterface *mScriptInterface; + QString mCurrentGesturePath; }; #endif diff --git a/src/ui/inputscriptinterface.cpp b/src/ui/inputscriptinterface.cpp index df57c6c..06f9c64 100644 --- a/src/ui/inputscriptinterface.cpp +++ b/src/ui/inputscriptinterface.cpp @@ -1,5 +1,6 @@ #include "inputscriptinterface.h" #include "mainwindow.h" +#include "displaywidget.h" #include <QtCore/QMetaEnum> #include <QtGui/QApplication> @@ -83,7 +84,7 @@ void InputScriptInterface::rightClick(qint32 x, qint32 y) } -QPoint InputScriptInterface::mapPositionToDevice(QPoint position) +QPoint InputScriptInterface::mapPositionToDevice(const QPoint &position) const { DeviceData d = mUi->deviceItem()->mDeviceData; QPoint returnedPosition; @@ -196,3 +197,27 @@ void InputScriptInterface::type(const QString &string) type(c); } } + +int InputScriptInterface::mouseX() const +{ + QPointF pos = mView->mapFromGlobal(QCursor::pos()); + pos = mDisplay->mapFromScene(pos); + return pos.x() - mUi->deviceItem()->mDeviceData.availableGeometry.x(); +} + +int InputScriptInterface::mouseY() const +{ + QPointF pos = mView->mapFromGlobal(QCursor::pos()); + pos = mDisplay->mapFromScene(pos); + return pos.y() - mUi->deviceItem()->mDeviceData.availableGeometry.y(); +} + +void InputScriptInterface::setView(QGraphicsView *view) +{ + mView = view; +} + +void InputScriptInterface::setDisplay(DisplayWidget *display) +{ + mDisplay = display; +} diff --git a/src/ui/inputscriptinterface.h b/src/ui/inputscriptinterface.h index 853e4ea..4feb057 100644 --- a/src/ui/inputscriptinterface.h +++ b/src/ui/inputscriptinterface.h @@ -5,6 +5,8 @@ #include <QtCore/QPoint> class MainWindow; +class QGraphicsView; +class DisplayWidget; class InputScriptInterface : public QObject { @@ -28,10 +30,16 @@ public: InputScriptInterface(MainWindow *mUi, QWidget *viewport); virtual ~InputScriptInterface(); + void setView(QGraphicsView *view); + void setDisplay(DisplayWidget *display); + Q_INVOKABLE void mousePress(MouseButton button, qint32 x, qint32 y); Q_INVOKABLE void mouseMove(qint32 x, qint32 y); Q_INVOKABLE void mouseRelease(MouseButton button, qint32 x, qint32 y); + Q_INVOKABLE int mouseX() const; + Q_INVOKABLE int mouseY() const; + Q_INVOKABLE void click(qint32 x, qint32 y); Q_INVOKABLE void doubleClick(qint32 x, qint32 y); Q_INVOKABLE void rightClick(qint32 x, qint32 y); @@ -43,11 +51,14 @@ public: private: void type(QChar c); void mousePress(MouseButton button, qint32 x, qint32 y, bool doubleClick); - QPoint mapPositionToDevice(QPoint position); + QPoint mapPositionToDevice(const QPoint &position) const; + QPoint mapPositionToScreen(const QPoint &position) const; MainWindow *mUi; QWidget *mViewport; Qt::MouseButtons mPressedButtons; + QGraphicsView *mView; + DisplayWidget *mDisplay; }; #endif // INPUTSCRIPTINTERFACE_H diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 5c77811..9a4475a 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -249,6 +249,16 @@ MainWindow::MainWindow(QWidget *parent) mobility->mNfcUi = nfcUi; config->addPage(nfcUi); + mTouchUi = new MultiPointTouchUi(this); + mTouchUi->setGestureScriptPath(userResourcePath() + "/scripts/gestures"); + config->addPage(mTouchUi); + connect(mTouchUi, SIGNAL(inputModeChanged(MultiPointTouchUi::InputMode)), + widgetManager, SLOT(setMouseInputMode(MultiPointTouchUi::InputMode))); + connect(this, SIGNAL(mouseInputModeChanged(MultiPointTouchUi::InputMode)), + mTouchUi, SLOT(setInputMode(MultiPointTouchUi::InputMode))); + connect(mTouchUi, SIGNAL(customGesturePathChanged(QString)), + widgetManager, SLOT(setCurrentGesturePath(QString))); + ScriptUi *scriptUi = new ScriptUi(scriptAdapter, this); FavoriteScriptButton *scriptButton = new FavoriteScriptButton(this); setupScriptDirectories(scriptUi, scriptButton); @@ -288,6 +298,8 @@ MainWindow::MainWindow(QWidget *parent) config->addMenuButton(scriptButton); InputScriptInterface *inputScriptInterface = new InputScriptInterface(this, view->viewport()); + inputScriptInterface->setView(view); + inputScriptInterface->setDisplay(deviceItem()->display()); // register script interfaces scriptAdapter->addScriptInterface("simulator", viewUi->scriptInterface()); @@ -298,13 +310,16 @@ MainWindow::MainWindow(QWidget *parent) scriptAdapter->addScriptInterface("sysinfo.storage", storageSystemInfoUi->scriptInterface()); scriptAdapter->addScriptInterface("camera", cameraUi->scriptInterface()); scriptAdapter->addScriptInterface("input", inputScriptInterface); + scriptAdapter->addScriptInterface("touch", widgetManager->scriptInterface()); connect(viewUi, SIGNAL(deviceSelectionChanged(const DeviceData &)), SLOT(callDeviceScript(const DeviceData &))); + connect(widgetManager, SIGNAL(gestureScriptRequested(QString)), scriptAdapter, SLOT(run(QString))); config->setWindowFlags(Qt::Tool); // read settings QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + mTouchUi->readSettings(settings); mobility->setInitialData(); @@ -333,6 +348,17 @@ bool MainWindow::eventFilter(QObject *watched, QEvent *event) && keyEvent->modifiers() & Qt::ControlModifier) { debugWindow->show(); + } else if (keyEvent->modifiers() & Qt::AltModifier) { + if (keyEvent->key() == Qt::Key_1) + emit mouseInputModeChanged(MultiPointTouchUi::defaultMode); + else if (keyEvent->key() == Qt::Key_2) + emit mouseInputModeChanged(MultiPointTouchUi::pinchMode); + else if (keyEvent->key() == Qt::Key_3) + emit mouseInputModeChanged(MultiPointTouchUi::panMode); + else if (keyEvent->key() == Qt::Key_4) + emit mouseInputModeChanged(MultiPointTouchUi::swipeMode); + else if (keyEvent->key() == Qt::Key_5) + emit mouseInputModeChanged(MultiPointTouchUi::freeMode); } } } @@ -352,6 +378,7 @@ void MainWindow::closeEvent(QCloseEvent *event) QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); writeSettings(settings); config->writeSettings(settings); + mTouchUi->writeSettings(settings); } } diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index 668cf47..94dcb77 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -36,6 +36,7 @@ #include "deviceitem.h" #include <QtGui/QWidget> #include "qsimulatordata_p.h" +#include "multipointtouchui.h" class DeviceItem; class ApplicationManager; @@ -77,6 +78,9 @@ private slots: void callDeviceScript(const DeviceData &newDevice); void activateWindow(); +signals: + void mouseInputModeChanged(MultiPointTouchUi::InputMode); + private: void writeSettings(QSettings &) const; void readSettings(QSettings &); @@ -94,6 +98,8 @@ private: ScriptAdapter *scriptAdapter; + MultiPointTouchUi *mTouchUi; + QWidget *debugWindow; bool startupError; diff --git a/src/ui/multipointtouchui.cpp b/src/ui/multipointtouchui.cpp new file mode 100644 index 0000000..8758734 --- /dev/null +++ b/src/ui/multipointtouchui.cpp @@ -0,0 +1,157 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#include "multipointtouchui.h" +#include <remotecontrolwidget/optionsitem.h> + +#include <QtCore/QSettings> +#include <QtGui/QVBoxLayout> +#include <QtGui/QButtonGroup> +#include <QtGui/QRadioButton> +#include <QtGui/QLineEdit> +#include <QtGui/QPushButton> +#include <QtGui/QFileDialog> + +MultiPointTouchUi::MultiPointTouchUi(QWidget *parent) : + ToolBoxPage(parent) +{ + QStringList tags; + QList<OptionsItem *> optionsList; + tags << tr("multi point touch"); + + mDefaultRadio = new QRadioButton(tr("Default mode")); + mPinchRadio = new QRadioButton(tr("Pinch mode")); + mPanRadio = new QRadioButton(tr("Pan mode")); + mSwipeRadio = new QRadioButton(tr("Swipe mode")); + mFreeRadio = new QRadioButton(tr("Free mode")); + mCustomLineEdit = new QLineEdit(); + QPushButton *loadButton = new QPushButton(tr("Browse")); + connect(loadButton, SIGNAL(clicked()), this, SLOT(getCustomGesturePath())); + connect (mCustomLineEdit, SIGNAL(editingFinished()), SLOT(emitCustomGesturePathChanged())); + + QButtonGroup *buttonGroup = new QButtonGroup(this); + buttonGroup->addButton(mDefaultRadio, 0); + buttonGroup->addButton(mPinchRadio, 1); + buttonGroup->addButton(mPanRadio, 2); + buttonGroup->addButton(mSwipeRadio, 3); + buttonGroup->addButton(mFreeRadio, 4); + mDefaultRadio->setChecked(true); + + QHBoxLayout *hLayout = new QHBoxLayout(); + hLayout->addWidget(mFreeRadio); + hLayout->addWidget(mCustomLineEdit); + hLayout->addWidget(loadButton); + + QVBoxLayout *vLayout = new QVBoxLayout(); + vLayout->addWidget(mDefaultRadio); + vLayout->addWidget(mPinchRadio); + vLayout->addWidget(mPanRadio); + vLayout->addWidget(mSwipeRadio); + vLayout->addLayout(hLayout); + QWidget *widget = new QWidget; + widget->setLayout(vLayout); + + connect(buttonGroup, SIGNAL(buttonClicked(int)), SLOT(emitInputModeChanged(int))); + OptionsItem *item = new OptionsItem(tr(""), widget, true); + optionsList << item; + setTitle(tr("Multipoint-touch mode")); + setOptions(optionsList); +} + +MultiPointTouchUi::~MultiPointTouchUi() +{ +} + +void MultiPointTouchUi::emitInputModeChanged(int newMode) +{ + emit inputModeChanged(static_cast<InputMode>(newMode)); +} + +void MultiPointTouchUi::setInputMode(MultiPointTouchUi::InputMode inputMode) +{ + switch (inputMode) { + case defaultMode: + mDefaultRadio->setChecked(true); + break; + case pinchMode: + mPinchRadio->setChecked(true); + break; + case panMode: + mPanRadio->setChecked(true); + break; + case swipeMode: + mSwipeRadio->setChecked(true); + break; + case freeMode: + mFreeRadio->setChecked(true); + break; + } + emit inputModeChanged(inputMode); +} + +void MultiPointTouchUi::getCustomGesturePath() +{ + mCustomLineEdit->setText(QFileDialog::getOpenFileName(this, tr("Choose gesture script"), + mGestureScriptPath, tr("Qt scripts (*.js *.qs)"))); + emitCustomGesturePathChanged(); +} + +void MultiPointTouchUi::emitCustomGesturePathChanged() +{ + emit customGesturePathChanged(mCustomLineEdit->text()); +} + +void MultiPointTouchUi::setGestureScriptPath(const QString &path) +{ + mGestureScriptPath = path; +} + +void MultiPointTouchUi::writeSettings(QSettings &settings) const +{ + ToolBoxPage::writeSettings(settings); + if (!QFile::exists(mCustomLineEdit->text())) + return; + + settings.beginGroup(title()); + settings.setValue("customGesturePath", mCustomLineEdit->text()); + settings.endGroup(); +} + +void MultiPointTouchUi::readSettings(QSettings &settings) +{ + ToolBoxPage::readSettings(settings); + settings.beginGroup(title()); + if (settings.contains("customGesturePath")) + mCustomLineEdit->setText(settings.value("customGesturePath").toString()); + settings.endGroup(); +} diff --git a/src/ui/multipointtouchui.h b/src/ui/multipointtouchui.h new file mode 100644 index 0000000..a427366 --- /dev/null +++ b/src/ui/multipointtouchui.h @@ -0,0 +1,89 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +**************************************************************************/ + +#ifndef MULTIPOINTTOUCHUI_H +#define MULTIPOINTTOUCHUI_H + +#include <QtCore/QObject> + +#include <remotecontrolwidget/toolbox.h> + +class MultiPointTouchUi; +class QRadioButton; +class QLineEdit; + +class MultiPointTouchUi : public ToolBoxPage +{ + Q_OBJECT +public: + enum InputMode { + defaultMode, + pinchMode, + panMode, + swipeMode, + freeMode + }; + + explicit MultiPointTouchUi(QWidget *parent = 0); + virtual ~MultiPointTouchUi(); + + void setGestureScriptPath(const QString &path); + void writeSettings(QSettings &settings) const; + void readSettings(QSettings &settings); + +signals: + void inputModeChanged(MultiPointTouchUi::InputMode newMode); + void customGesturePathChanged(const QString &path); + +private slots: + void emitInputModeChanged(int newMode); + void emitCustomGesturePathChanged(); + void getCustomGesturePath(); + +public slots: + void setInputMode(MultiPointTouchUi::InputMode inputMode); + +private: + InputMode mInputMode; + + QRadioButton *mDefaultRadio; + QRadioButton *mPinchRadio; + QRadioButton *mPanRadio; + QRadioButton *mSwipeRadio; + QRadioButton *mFreeRadio; + + QLineEdit *mCustomLineEdit; + QString mGestureScriptPath; +}; + +#endif // MULTIPOINTTOUCHUI_H diff --git a/src/ui/ui.pri b/src/ui/ui.pri index ca2f1e5..f9fc534 100644 --- a/src/ui/ui.pri +++ b/src/ui/ui.pri @@ -19,6 +19,7 @@ HEADERS += applicationtablewidget.h \ inputscriptinterface.h \ applicationui.h \ viewui.h \ + multipointtouchui.h SOURCES += applicationtablewidget.cpp \ mainwindow.cpp \ @@ -39,6 +40,7 @@ SOURCES += applicationtablewidget.cpp \ inputscriptinterface.cpp \ applicationui.cpp \ viewui.cpp \ + multipointtouchui.cpp FORMS += inspector.ui \ viewconfiguration.ui |