summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/qnamespace.qdoc5
-rw-r--r--examples/examples.pro3
-rw-r--r--examples/multitouch/fingerpaint/fingerpaint.pro11
-rw-r--r--examples/multitouch/fingerpaint/main.cpp52
-rw-r--r--examples/multitouch/fingerpaint/mainwindow.cpp218
-rw-r--r--examples/multitouch/fingerpaint/mainwindow.h89
-rw-r--r--examples/multitouch/fingerpaint/scribblearea.cpp213
-rw-r--r--examples/multitouch/fingerpaint/scribblearea.h81
-rw-r--r--examples/multitouch/knobs/knob.cpp93
-rw-r--r--examples/multitouch/knobs/knob.h55
-rw-r--r--examples/multitouch/knobs/knobs.pro2
-rw-r--r--examples/multitouch/knobs/main.cpp66
-rw-r--r--examples/multitouch/multitouch.pro2
-rw-r--r--examples/multitouch/pinchzoom/graphicsview.cpp81
-rw-r--r--examples/multitouch/pinchzoom/graphicsview.h53
-rw-r--r--examples/multitouch/pinchzoom/images/cheese.jpgbin0 -> 3029 bytes
-rw-r--r--examples/multitouch/pinchzoom/main.cpp87
-rw-r--r--examples/multitouch/pinchzoom/mice.qrc5
-rw-r--r--examples/multitouch/pinchzoom/mouse.cpp200
-rw-r--r--examples/multitouch/pinchzoom/mouse.h72
-rw-r--r--examples/multitouch/pinchzoom/pinchzoom.pro16
-rw-r--r--src/corelib/global/qnamespace.h10
-rw-r--r--src/corelib/kernel/qcoreevent.cpp6
-rw-r--r--src/corelib/kernel/qcoreevent.h7
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp25
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h2
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h2
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp166
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h6
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.cpp338
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.h64
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp106
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h5
-rw-r--r--src/gui/kernel/qapplication.cpp102
-rw-r--r--src/gui/kernel/qapplication_p.h33
-rw-r--r--src/gui/kernel/qapplication_win.cpp260
-rw-r--r--src/gui/kernel/qevent.cpp164
-rw-r--r--src/gui/kernel/qevent.h45
-rw-r--r--src/gui/kernel/qevent_p.h17
-rw-r--r--src/gui/kernel/qwidget.cpp3
-rw-r--r--src/gui/kernel/qwidget_p.h3
-rw-r--r--src/gui/kernel/qwidget_win.cpp4
-rw-r--r--src/network/kernel/qauthenticator.cpp2
-rw-r--r--tests/auto/qapplication/tst_qapplication.cpp143
-rw-r--r--tests/manual/qtouchevent/form.ui1897
-rw-r--r--tests/manual/qtouchevent/main.cpp554
-rw-r--r--tests/manual/qtouchevent/multitouch.pro5
-rw-r--r--tests/manual/qtouchevent/touchwidget.cpp94
-rw-r--r--tests/manual/qtouchevent/touchwidget.h31
49 files changed, 5459 insertions, 39 deletions
diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc
index ad59b8d..98f7e7c 100644
--- a/doc/src/qnamespace.qdoc
+++ b/doc/src/qnamespace.qdoc
@@ -1191,6 +1191,11 @@
on Mac when using Carbon. This attribute has no effect on Cocoa.
The attribute is off by default and can be enabled on a per-window basis.
+ \value WA_AcceptTouchEvents Allows touch events (see QTouchEvent)
+ to be sent to the widget. Must be set on all widgets that can
+ handle touch events. Without this attribute set, events from a
+ touch device will be sent as mouse events.
+
\omitvalue WA_SetLayoutDirection
\omitvalue WA_InputMethodTransparent
\omitvalue WA_WState_CompressKeys
diff --git a/examples/examples.pro b/examples/examples.pro
index 41501a0..2d49103 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -20,7 +20,8 @@ SUBDIRS = \
widgets \
uitools \
xml \
- script
+ script \
+ multitouch
contains(QT_CONFIG, phonon):!static: SUBDIRS += phonon
contains(QT_CONFIG, webkit): SUBDIRS += webkit
diff --git a/examples/multitouch/fingerpaint/fingerpaint.pro b/examples/multitouch/fingerpaint/fingerpaint.pro
new file mode 100644
index 0000000..1d45635
--- /dev/null
+++ b/examples/multitouch/fingerpaint/fingerpaint.pro
@@ -0,0 +1,11 @@
+HEADERS = mainwindow.h \
+ scribblearea.h
+SOURCES = main.cpp \
+ mainwindow.cpp \
+ scribblearea.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/multitouch/fingerpaint
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS fingerpaint.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/multitouch/fingerpaint
+INSTALLS += target sources
diff --git a/examples/multitouch/fingerpaint/main.cpp b/examples/multitouch/fingerpaint/main.cpp
new file mode 100644
index 0000000..49bf25b
--- /dev/null
+++ b/examples/multitouch/fingerpaint/main.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ MainWindow window;
+ window.showMaximized();
+ return app.exec();
+}
diff --git a/examples/multitouch/fingerpaint/mainwindow.cpp b/examples/multitouch/fingerpaint/mainwindow.cpp
new file mode 100644
index 0000000..e510f89
--- /dev/null
+++ b/examples/multitouch/fingerpaint/mainwindow.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "mainwindow.h"
+#include "scribblearea.h"
+
+//! [0]
+MainWindow::MainWindow()
+{
+ scribbleArea = new ScribbleArea;
+ setCentralWidget(scribbleArea);
+
+ createActions();
+ createMenus();
+
+ setWindowTitle(tr("Finger Paint"));
+ resize(500, 500);
+}
+//! [0]
+
+//! [1]
+void MainWindow::closeEvent(QCloseEvent *event)
+//! [1] //! [2]
+{
+ if (maybeSave()) {
+ event->accept();
+ } else {
+ event->ignore();
+ }
+}
+//! [2]
+
+//! [3]
+void MainWindow::open()
+//! [3] //! [4]
+{
+ if (maybeSave()) {
+ QString fileName = QFileDialog::getOpenFileName(this,
+ tr("Open File"), QDir::currentPath());
+ if (!fileName.isEmpty())
+ scribbleArea->openImage(fileName);
+ }
+}
+//! [4]
+
+//! [5]
+void MainWindow::save()
+//! [5] //! [6]
+{
+ QAction *action = qobject_cast<QAction *>(sender());
+ QByteArray fileFormat = action->data().toByteArray();
+ saveFile(fileFormat);
+}
+//! [6]
+
+//! [11]
+void MainWindow::about()
+//! [11] //! [12]
+{
+ QMessageBox::about(this, tr("About Scribble"),
+ tr("<p>The <b>Scribble</b> example shows how to use QMainWindow as the "
+ "base widget for an application, and how to reimplement some of "
+ "QWidget's event handlers to receive the events generated for "
+ "the application's widgets:</p><p> We reimplement the mouse event "
+ "handlers to facilitate drawing, the paint event handler to "
+ "update the application and the resize event handler to optimize "
+ "the application's appearance. In addition we reimplement the "
+ "close event handler to intercept the close events before "
+ "terminating the application.</p><p> The example also demonstrates "
+ "how to use QPainter to draw an image in real time, as well as "
+ "to repaint widgets.</p>"));
+}
+//! [12]
+
+//! [13]
+void MainWindow::createActions()
+//! [13] //! [14]
+{
+ openAct = new QAction(tr("&Open..."), this);
+ openAct->setShortcut(tr("Ctrl+O"));
+ connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
+
+ foreach (QByteArray format, QImageWriter::supportedImageFormats()) {
+ QString text = tr("%1...").arg(QString(format).toUpper());
+
+ QAction *action = new QAction(text, this);
+ action->setData(format);
+ connect(action, SIGNAL(triggered()), this, SLOT(save()));
+ saveAsActs.append(action);
+ }
+
+ printAct = new QAction(tr("&Print..."), this);
+ connect(printAct, SIGNAL(triggered()), scribbleArea, SLOT(print()));
+
+ exitAct = new QAction(tr("E&xit"), this);
+ exitAct->setShortcut(tr("Ctrl+Q"));
+ connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
+
+ clearScreenAct = new QAction(tr("&Clear Screen"), this);
+ clearScreenAct->setShortcut(tr("Ctrl+L"));
+ connect(clearScreenAct, SIGNAL(triggered()),
+ scribbleArea, SLOT(clearImage()));
+
+ aboutAct = new QAction(tr("&About"), this);
+ connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
+
+ aboutQtAct = new QAction(tr("About &Qt"), this);
+ connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+}
+//! [14]
+
+//! [15]
+void MainWindow::createMenus()
+//! [15] //! [16]
+{
+ saveAsMenu = new QMenu(tr("&Save As"), this);
+ foreach (QAction *action, saveAsActs)
+ saveAsMenu->addAction(action);
+
+ fileMenu = new QMenu(tr("&File"), this);
+ fileMenu->addAction(openAct);
+ fileMenu->addMenu(saveAsMenu);
+ fileMenu->addAction(printAct);
+ fileMenu->addSeparator();
+ fileMenu->addAction(exitAct);
+
+ optionMenu = new QMenu(tr("&Options"), this);
+ optionMenu->addAction(clearScreenAct);
+
+ helpMenu = new QMenu(tr("&Help"), this);
+ helpMenu->addAction(aboutAct);
+ helpMenu->addAction(aboutQtAct);
+
+ menuBar()->addMenu(fileMenu);
+ menuBar()->addMenu(optionMenu);
+ menuBar()->addMenu(helpMenu);
+}
+//! [16]
+
+//! [17]
+bool MainWindow::maybeSave()
+//! [17] //! [18]
+{
+ if (scribbleArea->isModified()) {
+ QMessageBox::StandardButton ret;
+ ret = QMessageBox::warning(this, tr("Scribble"),
+ tr("The image has been modified.\n"
+ "Do you want to save your changes?"),
+ QMessageBox::Save | QMessageBox::Discard
+ | QMessageBox::Cancel);
+ if (ret == QMessageBox::Save) {
+ return saveFile("png");
+ } else if (ret == QMessageBox::Cancel) {
+ return false;
+ }
+ }
+ return true;
+}
+//! [18]
+
+//! [19]
+bool MainWindow::saveFile(const QByteArray &fileFormat)
+//! [19] //! [20]
+{
+ QString initialPath = QDir::currentPath() + "/untitled." + fileFormat;
+
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),
+ initialPath,
+ tr("%1 Files (*.%2);;All Files (*)")
+ .arg(QString(fileFormat.toUpper()))
+ .arg(QString(fileFormat)));
+ if (fileName.isEmpty()) {
+ return false;
+ } else {
+ return scribbleArea->saveImage(fileName, fileFormat);
+ }
+}
+//! [20]
diff --git a/examples/multitouch/fingerpaint/mainwindow.h b/examples/multitouch/fingerpaint/mainwindow.h
new file mode 100644
index 0000000..fdb790d
--- /dev/null
+++ b/examples/multitouch/fingerpaint/mainwindow.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QList>
+#include <QMainWindow>
+
+class ScribbleArea;
+
+//! [0]
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow();
+
+protected:
+ void closeEvent(QCloseEvent *event);
+
+private slots:
+ void open();
+ void save();
+ void about();
+
+private:
+ void createActions();
+ void createMenus();
+ bool maybeSave();
+ bool saveFile(const QByteArray &fileFormat);
+
+ ScribbleArea *scribbleArea;
+
+ QMenu *saveAsMenu;
+ QMenu *fileMenu;
+ QMenu *optionMenu;
+ QMenu *helpMenu;
+
+ QAction *openAct;
+ QList<QAction *> saveAsActs;
+ QAction *exitAct;
+ QAction *printAct;
+ QAction *clearScreenAct;
+ QAction *aboutAct;
+ QAction *aboutQtAct;
+};
+//! [0]
+
+#endif
diff --git a/examples/multitouch/fingerpaint/scribblearea.cpp b/examples/multitouch/fingerpaint/scribblearea.cpp
new file mode 100644
index 0000000..a042fe7
--- /dev/null
+++ b/examples/multitouch/fingerpaint/scribblearea.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "scribblearea.h"
+
+//! [0]
+ScribbleArea::ScribbleArea(QWidget *parent)
+ : QWidget(parent)
+{
+ setAttribute(Qt::WA_AcceptTouchEvents);
+ setAttribute(Qt::WA_StaticContents);
+ modified = false;
+
+ myPenColors
+ << QColor("green")
+ << QColor("purple")
+ << QColor("red")
+ << QColor("blue")
+ << QColor("yellow")
+
+ << QColor("pink")
+ << QColor("orange")
+ << QColor("brown")
+ << QColor("grey")
+ << QColor("black");
+}
+//! [0]
+
+//! [1]
+bool ScribbleArea::openImage(const QString &fileName)
+//! [1] //! [2]
+{
+ QImage loadedImage;
+ if (!loadedImage.load(fileName))
+ return false;
+
+ QSize newSize = loadedImage.size().expandedTo(size());
+ resizeImage(&loadedImage, newSize);
+ image = loadedImage;
+ modified = false;
+ update();
+ return true;
+}
+//! [2]
+
+//! [3]
+bool ScribbleArea::saveImage(const QString &fileName, const char *fileFormat)
+//! [3] //! [4]
+{
+ QImage visibleImage = image;
+ resizeImage(&visibleImage, size());
+
+ if (visibleImage.save(fileName, fileFormat)) {
+ modified = false;
+ return true;
+ } else {
+ return false;
+ }
+}
+//! [4]
+
+//! [9]
+void ScribbleArea::clearImage()
+//! [9] //! [10]
+{
+ image.fill(qRgb(255, 255, 255));
+ modified = true;
+ update();
+}
+//! [10]
+
+//! [12] //! [13]
+void ScribbleArea::paintEvent(QPaintEvent *event)
+//! [13] //! [14]
+{
+ QPainter painter(this);
+ const QRect rect = event->rect();
+ painter.drawImage(rect.topLeft(), image, rect);
+}
+//! [14]
+
+//! [15]
+void ScribbleArea::resizeEvent(QResizeEvent *event)
+//! [15] //! [16]
+{
+ if (width() > image.width() || height() > image.height()) {
+ int newWidth = qMax(width() + 128, image.width());
+ int newHeight = qMax(height() + 128, image.height());
+ resizeImage(&image, QSize(newWidth, newHeight));
+ update();
+ }
+ QWidget::resizeEvent(event);
+}
+//! [16]
+
+//! [19]
+void ScribbleArea::resizeImage(QImage *image, const QSize &newSize)
+//! [19] //! [20]
+{
+ if (image->size() == newSize)
+ return;
+
+ QImage newImage(newSize, QImage::Format_RGB32);
+ newImage.fill(qRgb(255, 255, 255));
+ QPainter painter(&newImage);
+ painter.drawImage(QPoint(0, 0), *image);
+ *image = newImage;
+}
+//! [20]
+
+//! [21]
+void ScribbleArea::print()
+{
+#ifndef QT_NO_PRINTER
+ QPrinter printer(QPrinter::HighResolution);
+
+ QPrintDialog *printDialog = new QPrintDialog(&printer, this);
+//! [21] //! [22]
+ if (printDialog->exec() == QDialog::Accepted) {
+ QPainter painter(&printer);
+ QRect rect = painter.viewport();
+ QSize size = image.size();
+ size.scale(rect.size(), Qt::KeepAspectRatio);
+ painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
+ painter.setWindow(image.rect());
+ painter.drawImage(0, 0, image);
+ }
+#endif // QT_NO_PRINTER
+}
+//! [22]
+
+bool ScribbleArea::event(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ {
+ QList<QTouchEvent::TouchPoint *> touchPoints = static_cast<QTouchEvent *>(event)->touchPoints();
+ foreach (QTouchEvent::TouchPoint *touchPoint, touchPoints) {
+ switch (touchPoint->state()) {
+ case Qt::TouchPointStationary:
+ // don't do anything if this touch point hasn't moved
+ continue;
+ default:
+ {
+ int diameter = int(50 * touchPoint->pressure());
+ QRectF rectF(0, 0, diameter, diameter);
+ rectF.moveCenter(touchPoint->pos());
+ QRect rect = rectF.toRect();
+
+ QPainter painter(&image);
+ painter.setPen(Qt::NoPen);
+ painter.setBrush(myPenColors.at(touchPoint->id()));
+ painter.drawEllipse(rectF);
+ painter.end();
+
+ modified = true;
+ int rad = 2;
+ update(rect.adjusted(-rad,-rad, +rad, +rad));
+ }
+ break;
+ }
+ }
+
+ event->accept();
+ return true;
+ }
+ default:
+ break;
+ }
+ return QWidget::event(event);
+}
diff --git a/examples/multitouch/fingerpaint/scribblearea.h b/examples/multitouch/fingerpaint/scribblearea.h
new file mode 100644
index 0000000..8928ce1
--- /dev/null
+++ b/examples/multitouch/fingerpaint/scribblearea.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SCRIBBLEAREA_H
+#define SCRIBBLEAREA_H
+
+#include <QColor>
+#include <QImage>
+#include <QPoint>
+#include <QWidget>
+
+//! [0]
+class ScribbleArea : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ScribbleArea(QWidget *parent = 0);
+
+ bool openImage(const QString &fileName);
+ bool saveImage(const QString &fileName, const char *fileFormat);
+
+ bool isModified() const { return modified; }
+
+public slots:
+ void clearImage();
+ void print();
+
+protected:
+ void paintEvent(QPaintEvent *event);
+ void resizeEvent(QResizeEvent *event);
+ bool event(QEvent *event);
+
+private:
+ void resizeImage(QImage *image, const QSize &newSize);
+
+ bool modified;
+ QList<QColor> myPenColors;
+ QImage image;
+};
+//! [0]
+
+#endif
diff --git a/examples/multitouch/knobs/knob.cpp b/examples/multitouch/knobs/knob.cpp
new file mode 100644
index 0000000..4622f69
--- /dev/null
+++ b/examples/multitouch/knobs/knob.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "knob.h"
+
+#include <QBrush>
+#include <QGraphicsSceneTouchEvent>
+
+Knob::Knob()
+ : QGraphicsEllipseItem(-50, -50, 100, 100)
+{
+ setAcceptTouchEvents(true);
+ setBrush(Qt::lightGray);
+
+ QGraphicsEllipseItem *leftItem = new QGraphicsEllipseItem(0, 0, 10, 10, this);
+ leftItem->setPos(-45, -5);
+ leftItem->setBrush(Qt::darkGreen);
+
+ QGraphicsEllipseItem *rightItem = new QGraphicsEllipseItem(0, 0, 10, 10, this);
+ rightItem->setPos(35, -5);
+ rightItem->setBrush(Qt::darkRed);
+}
+
+bool Knob::sceneEvent(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::GraphicsSceneTouchBegin:
+ event->accept();
+ break;
+
+ case QEvent::GraphicsSceneTouchUpdate:
+ case QEvent::GraphicsSceneTouchEnd:
+ {
+ QGraphicsSceneTouchEvent *touchEvent = static_cast<QGraphicsSceneTouchEvent *>(event);
+
+ if (touchEvent->touchPoints().count() == 2) {
+ QGraphicsSceneTouchEvent::TouchPoint *touchPoint1 = touchEvent->touchPoints().first();
+ QGraphicsSceneTouchEvent::TouchPoint *touchPoint2 = touchEvent->touchPoints().last();
+
+ QLineF line1(touchPoint1->lastScenePos(), touchPoint2->lastScenePos());
+ QLineF line2(touchPoint1->scenePos(), touchPoint2->scenePos());
+
+ rotate(line2.angleTo(line1));
+ }
+
+ touchEvent->accept();
+ break;
+ }
+
+ default:
+ return QGraphicsItem::sceneEvent(event);
+ }
+
+ return true;
+}
diff --git a/examples/multitouch/knobs/knob.h b/examples/multitouch/knobs/knob.h
new file mode 100644
index 0000000..1079483
--- /dev/null
+++ b/examples/multitouch/knobs/knob.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef KNOB_H
+#define KNOB_H
+
+#include <QGraphicsItem>
+
+class Knob : public QGraphicsEllipseItem
+{
+public:
+ Knob();
+
+ bool sceneEvent(QEvent *event);
+};
+
+#endif // KNOB_H
diff --git a/examples/multitouch/knobs/knobs.pro b/examples/multitouch/knobs/knobs.pro
new file mode 100644
index 0000000..90f0ba5
--- /dev/null
+++ b/examples/multitouch/knobs/knobs.pro
@@ -0,0 +1,2 @@
+HEADERS = knob.h
+SOURCES = main.cpp knob.cpp
diff --git a/examples/multitouch/knobs/main.cpp b/examples/multitouch/knobs/main.cpp
new file mode 100644
index 0000000..8f78cf9
--- /dev/null
+++ b/examples/multitouch/knobs/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QGraphicsView>
+
+#include "knob.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
+
+ Knob *knob1 = new Knob;
+ knob1->setPos(-110, 0);
+ Knob *knob2 = new Knob;
+
+ scene.addItem(knob1);
+ scene.addItem(knob2);
+
+ view.showMaximized();
+ view.fitInView(scene.sceneRect().adjusted(-20, -20, 20, 20), Qt::KeepAspectRatio);
+
+ return app.exec();
+}
diff --git a/examples/multitouch/multitouch.pro b/examples/multitouch/multitouch.pro
new file mode 100644
index 0000000..b3d1d55
--- /dev/null
+++ b/examples/multitouch/multitouch.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = pinchzoom fingerpaint knobs
diff --git a/examples/multitouch/pinchzoom/graphicsview.cpp b/examples/multitouch/pinchzoom/graphicsview.cpp
new file mode 100644
index 0000000..f763e6f
--- /dev/null
+++ b/examples/multitouch/pinchzoom/graphicsview.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphicsview.h"
+
+#include <QScrollBar>
+#include <QTouchEvent>
+
+GraphicsView::GraphicsView(QGraphicsScene *scene, QWidget *parent)
+ : QGraphicsView(scene, parent)
+{
+ setAttribute(Qt::WA_AcceptTouchEvents);
+}
+
+bool GraphicsView::event(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ {
+ QList<QTouchEvent::TouchPoint *> touchPoints = static_cast<QTouchEvent *>(event)->touchPoints();
+ if (touchPoints.count() == 1) {
+ const QTouchEvent::TouchPoint *touchPoint = touchPoints.first();
+ QPointF delta = touchPoint->pos() - touchPoint->lastPos();
+ horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x());
+ verticalScrollBar()->setValue(verticalScrollBar()->value() - delta.y());
+ } else if (touchPoints.count() == 2) {
+ // determine scale factor
+ const QTouchEvent::TouchPoint *touchPoint0 = touchPoints.first();
+ const QTouchEvent::TouchPoint *touchPoint1 = touchPoints.last();
+ const qreal scaleFactor = QLineF(touchPoint0->pos(), touchPoint1->pos()).length()
+ / QLineF(touchPoint0->startPos(), touchPoint1->startPos()).length();
+ setTransform(QTransform().scale(scaleFactor, scaleFactor));
+ }
+ event->accept();
+ return true;
+ }
+ default:
+ break;
+ }
+ return QGraphicsView::event(event);
+}
diff --git a/examples/multitouch/pinchzoom/graphicsview.h b/examples/multitouch/pinchzoom/graphicsview.h
new file mode 100644
index 0000000..626f23c
--- /dev/null
+++ b/examples/multitouch/pinchzoom/graphicsview.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#include <QGraphicsView>
+
+class GraphicsView : public QGraphicsView
+{
+ Q_OBJECT
+
+public:
+ GraphicsView(QGraphicsScene *scene = 0, QWidget *parent = 0);
+
+ bool event(QEvent *event);
+};
diff --git a/examples/multitouch/pinchzoom/images/cheese.jpg b/examples/multitouch/pinchzoom/images/cheese.jpg
new file mode 100644
index 0000000..dea5795
--- /dev/null
+++ b/examples/multitouch/pinchzoom/images/cheese.jpg
Binary files differ
diff --git a/examples/multitouch/pinchzoom/main.cpp b/examples/multitouch/pinchzoom/main.cpp
new file mode 100644
index 0000000..bb86870
--- /dev/null
+++ b/examples/multitouch/pinchzoom/main.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphicsview.h"
+#include "mouse.h"
+
+#include <QtGui>
+
+#include <math.h>
+
+static const int MouseCount = 7;
+
+//! [0]
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
+//! [0]
+
+//! [1]
+ QGraphicsScene scene;
+ scene.setSceneRect(-300, -300, 600, 600);
+//! [1] //! [2]
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+//! [2]
+
+//! [3]
+ for (int i = 0; i < MouseCount; ++i) {
+ Mouse *mouse = new Mouse;
+ mouse->setPos(::sin((i * 6.28) / MouseCount) * 200,
+ ::cos((i * 6.28) / MouseCount) * 200);
+ scene.addItem(mouse);
+ }
+//! [3]
+
+//! [4]
+ GraphicsView view(&scene);
+ view.setRenderHint(QPainter::Antialiasing);
+ view.setBackgroundBrush(QPixmap(":/images/cheese.jpg"));
+//! [4] //! [5]
+ view.setCacheMode(QGraphicsView::CacheBackground);
+ view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+//! [5] //! [6]
+ view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice"));
+ view.showMaximized();
+
+ return app.exec();
+}
+//! [6]
diff --git a/examples/multitouch/pinchzoom/mice.qrc b/examples/multitouch/pinchzoom/mice.qrc
new file mode 100644
index 0000000..accdb4d
--- /dev/null
+++ b/examples/multitouch/pinchzoom/mice.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/" >
+ <file>images/cheese.jpg</file>
+ </qresource>
+</RCC>
diff --git a/examples/multitouch/pinchzoom/mouse.cpp b/examples/multitouch/pinchzoom/mouse.cpp
new file mode 100644
index 0000000..1d9fa89
--- /dev/null
+++ b/examples/multitouch/pinchzoom/mouse.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mouse.h"
+
+#include <QGraphicsScene>
+#include <QPainter>
+#include <QStyleOption>
+
+#include <math.h>
+
+static const double Pi = 3.14159265358979323846264338327950288419717;
+static double TwoPi = 2.0 * Pi;
+
+static qreal normalizeAngle(qreal angle)
+{
+ while (angle < 0)
+ angle += TwoPi;
+ while (angle > TwoPi)
+ angle -= TwoPi;
+ return angle;
+}
+
+//! [0]
+Mouse::Mouse()
+ : angle(0), speed(0), mouseEyeDirection(0),
+ color(qrand() % 256, qrand() % 256, qrand() % 256)
+{
+ rotate(qrand() % (360 * 16));
+ startTimer(1000 / 33);
+}
+//! [0]
+
+//! [1]
+QRectF Mouse::boundingRect() const
+{
+ qreal adjust = 0.5;
+ return QRectF(-18 - adjust, -22 - adjust,
+ 36 + adjust, 60 + adjust);
+}
+//! [1]
+
+//! [2]
+QPainterPath Mouse::shape() const
+{
+ QPainterPath path;
+ path.addRect(-10, -20, 20, 40);
+ return path;
+}
+//! [2]
+
+//! [3]
+void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ // Body
+ painter->setBrush(color);
+ painter->drawEllipse(-10, -20, 20, 40);
+
+ // Eyes
+ painter->setBrush(Qt::white);
+ painter->drawEllipse(-10, -17, 8, 8);
+ painter->drawEllipse(2, -17, 8, 8);
+
+ // Nose
+ painter->setBrush(Qt::black);
+ painter->drawEllipse(QRectF(-2, -22, 4, 4));
+
+ // Pupils
+ painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4));
+ painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4));
+
+ // Ears
+ painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red);
+ painter->drawEllipse(-17, -12, 16, 16);
+ painter->drawEllipse(1, -12, 16, 16);
+
+ // Tail
+ QPainterPath path(QPointF(0, 20));
+ path.cubicTo(-5, 22, -5, 22, 0, 25);
+ path.cubicTo(5, 27, 5, 32, 0, 30);
+ path.cubicTo(-5, 32, -5, 42, 0, 35);
+ painter->setBrush(Qt::NoBrush);
+ painter->drawPath(path);
+}
+//! [3]
+
+//! [4]
+void Mouse::timerEvent(QTimerEvent *)
+{
+//! [4]
+ // Don't move too far away
+//! [5]
+ QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
+ if (lineToCenter.length() > 150) {
+ qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());
+ if (lineToCenter.dy() < 0)
+ angleToCenter = TwoPi - angleToCenter;
+ angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);
+
+ if (angleToCenter < Pi && angleToCenter > Pi / 4) {
+ // Rotate left
+ angle += (angle < -Pi / 2) ? 0.25 : -0.25;
+ } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) {
+ // Rotate right
+ angle += (angle < Pi / 2) ? 0.25 : -0.25;
+ }
+ } else if (::sin(angle) < 0) {
+ angle += 0.25;
+ } else if (::sin(angle) > 0) {
+ angle -= 0.25;
+//! [5] //! [6]
+ }
+//! [6]
+
+ // Try not to crash with any other mice
+//! [7]
+ QList<QGraphicsItem *> dangerMice = scene()->items(QPolygonF()
+ << mapToScene(0, 0)
+ << mapToScene(-30, -50)
+ << mapToScene(30, -50));
+ foreach (QGraphicsItem *item, dangerMice) {
+ if (item == this)
+ continue;
+
+ QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
+ qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());
+ if (lineToMouse.dy() < 0)
+ angleToMouse = TwoPi - angleToMouse;
+ angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);
+
+ if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
+ // Rotate right
+ angle += 0.5;
+ } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) {
+ // Rotate left
+ angle -= 0.5;
+//! [7] //! [8]
+ }
+//! [8] //! [9]
+ }
+//! [9]
+
+ // Add some random movement
+//! [10]
+ if (dangerMice.size() > 1 && (qrand() % 10) == 0) {
+ if (qrand() % 1)
+ angle += (qrand() % 100) / 500.0;
+ else
+ angle -= (qrand() % 100) / 500.0;
+ }
+//! [10]
+
+//! [11]
+ speed += (-50 + qrand() % 100) / 100.0;
+
+ qreal dx = ::sin(angle) * 10;
+ mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5;
+
+ rotate(dx);
+ setPos(mapToParent(0, -(3 + sin(speed) * 3)));
+}
+//! [11]
diff --git a/examples/multitouch/pinchzoom/mouse.h b/examples/multitouch/pinchzoom/mouse.h
new file mode 100644
index 0000000..7545fe6
--- /dev/null
+++ b/examples/multitouch/pinchzoom/mouse.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MOUSE_H
+#define MOUSE_H
+
+#include <QGraphicsItem>
+#include <QObject>
+
+//! [0]
+class Mouse : public QObject, public QGraphicsItem
+{
+ Q_OBJECT
+
+public:
+ Mouse();
+
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget);
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ qreal angle;
+ qreal speed;
+ qreal mouseEyeDirection;
+ QColor color;
+};
+//! [0]
+
+#endif
diff --git a/examples/multitouch/pinchzoom/pinchzoom.pro b/examples/multitouch/pinchzoom/pinchzoom.pro
new file mode 100644
index 0000000..bd87cf7
--- /dev/null
+++ b/examples/multitouch/pinchzoom/pinchzoom.pro
@@ -0,0 +1,16 @@
+HEADERS += \
+ mouse.h \
+ graphicsview.h
+SOURCES += \
+ main.cpp \
+ mouse.cpp \
+ graphicsview.cpp
+
+RESOURCES += \
+ mice.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/multitouch/pinchzoom
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS pinchzoom.pro images
+sources.path = $$[QT_INSTALL_EXAMPLES]/multitouch/pinchzoom
+INSTALLS += target sources
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 4873b17..1635f8a 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -491,6 +491,9 @@ public:
WA_WState_WindowOpacitySet = 119, // internal
WA_TranslucentBackground = 120,
+ WA_AcceptTouchEvents = 121,
+ WA_AcceptedTouchBeginEvent = 122,
+
// Add new attributes before this line
WA_AttributeCount
};
@@ -1540,6 +1543,13 @@ public:
BottomLeftSection,
TitleBarArea // For move
};
+
+ enum TouchPointState {
+ TouchPointPressed,
+ TouchPointMoved,
+ TouchPointStationary,
+ TouchPointReleased
+ };
}
#ifdef Q_MOC_RUN
;
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 11a2d3c..ecc8796 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -222,6 +222,12 @@ QT_BEGIN_NAMESPACE
\value ZOrderChange The widget's z-order has changed. This event is never sent to top level windows.
\value KeyboardLayoutChange The keyboard layout has changed.
\value DynamicPropertyChange A dynamic property was added, changed or removed from the object.
+ \value TouchBegin Beginning of a sequence of touch-screen and/or track-pad events (QTouchEvent)
+ \value TouchUpdate Touch-screen event (QTouchEvent)
+ \value TouchEnd End of touch-event sequence (QTouchEvent)
+ \value GraphicsSceneTouchBegin Beginning of a sequence of touch-screen and/or track-pad events in a graphics scene (QGraphicsSceneTouchEvent)
+ \value GraphicsSceneTouchUpdate Touch-screen event in a graphics scene (QGraphicsSceneTouchEvent)
+ \value GraphicsSceneTouchEnd End of touch-event sequence in a graphics scene (QGraphicsSceneTouchEvent)
User events should have values between \c User and \c{MaxUser}:
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index fa472e6..42a75f8 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -266,6 +266,13 @@ public:
CocoaRequestModal = 190, // Internal for requesting an application modal Cocoa Window
MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear
+ TouchBegin = 193,
+ TouchUpdate = 194,
+ TouchEnd = 195,
+ GraphicsSceneTouchBegin = 196,
+ GraphicsSceneTouchUpdate = 197,
+ GraphicsSceneTouchEnd = 198,
+
// 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 743c16d..3eef396 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -2106,6 +2106,31 @@ void QGraphicsItem::setAcceptsHoverEvents(bool enabled)
setAcceptHoverEvents(enabled);
}
+/*! \since 4.6
+
+ Returns true if an item accepts touch events
+ (QGraphicsSceneTouchEvent); otherwise, returns false. By default,
+ items do not accept touch events.
+
+ \sa setAcceptTouchEvents()
+*/
+bool QGraphicsItem::acceptTouchEvents() const
+{
+ return d_ptr->acceptTouchEvents;
+}
+
+/*!
+ \since 4.6
+
+ If \a enabled is true, this item will accept touch events;
+ otherwise, it will ignore them. By default, items do not accept
+ touch events.
+*/
+void QGraphicsItem::setAcceptTouchEvents(bool enabled)
+{
+ d_ptr->acceptTouchEvents = quint32(enabled);
+}
+
/*!
Returns true if this item handles child events (i.e., all events
intended for any of its children are instead sent to this item);
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index b98882d..ec3373a 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -203,6 +203,8 @@ public:
void setAcceptsHoverEvents(bool enabled); // obsolete
bool acceptHoverEvents() const;
void setAcceptHoverEvents(bool enabled);
+ bool acceptTouchEvents() const;
+ void setAcceptTouchEvents(bool enabled);
bool handlesChildEvents() const;
void setHandlesChildEvents(bool enabled);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 2936cf1..5e77dfd 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -143,6 +143,7 @@ public:
emptyClipPath(0),
inSetPosHelper(0),
allChildrenCombineOpacity(1),
+ acceptTouchEvents(0),
globalStackingOrder(-1),
sceneTransformIndex(-1),
q_ptr(0)
@@ -327,6 +328,7 @@ public:
quint32 emptyClipPath : 1;
quint32 inSetPosHelper : 1;
quint32 allChildrenCombineOpacity : 1;
+ quint32 acceptTouchEvents : 1;
// Optional stacking order
int globalStackingOrder;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 69e08d1..f322305 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -3796,6 +3796,9 @@ bool QGraphicsScene::event(QEvent *event)
case QEvent::GraphicsSceneHoverEnter:
case QEvent::GraphicsSceneHoverLeave:
case QEvent::GraphicsSceneHoverMove:
+ case QEvent::GraphicsSceneTouchBegin:
+ case QEvent::GraphicsSceneTouchUpdate:
+ case QEvent::GraphicsSceneTouchEnd:
// Reset the under-mouse list to ensure that this event gets fresh
// item-under-mouse data. Be careful about this list; if people delete
// items from inside event handlers, this list can quickly end up
@@ -3947,6 +3950,15 @@ bool QGraphicsScene::event(QEvent *event)
// geometries that do not have an explicit style set.
update();
break;
+ case QEvent::GraphicsSceneTouchBegin:
+ d->touchBeginEvent(static_cast<QGraphicsSceneTouchEvent *>(event));
+ break;
+ case QEvent::GraphicsSceneTouchUpdate:
+ d->touchUpdateEvent(static_cast<QGraphicsSceneTouchEvent *>(event));
+ break;
+ case QEvent::GraphicsSceneTouchEnd:
+ d->touchEndEvent(static_cast<QGraphicsSceneTouchEvent *>(event));
+ break;
case QEvent::Timer:
if (d->indexTimerId && static_cast<QTimerEvent *>(event)->timerId() == d->indexTimerId) {
if (d->restartIndexTimer) {
@@ -5574,6 +5586,160 @@ void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget)
}
}
+// ### FIXME: the code for touch event support is mosly copied from
+// ### QGraphicsScenePrivate::mousePressEventHandler() and friends, need to
+// ### refactor to reduce code duplication
+
+void QGraphicsScenePrivate::sendTouchEvent(QGraphicsSceneTouchEvent *touchEvent)
+{
+ if (touchEvent->type() == QEvent::GraphicsSceneTouchEnd && lastMouseGrabberItemHasImplicitMouseGrab) {
+ clearMouseGrabber();
+ return;
+ }
+
+ QGraphicsItem *item = mouseGrabberItems.last();
+ QList<QGraphicsSceneTouchEvent::TouchPoint *> touchPoints = touchEvent->touchPoints();
+ for (int i = 0; i < touchPoints.count(); ++i) {
+ QGraphicsSceneTouchEvent::TouchPoint *touchPoint = touchPoints.at(i);
+ touchPoint->setPos(item->d_ptr->genericMapFromScene(touchPoint->scenePos(), touchEvent->widget()));
+ touchPoint->setStartPos(item->d_ptr->genericMapFromScene(touchPoint->startScenePos(), touchEvent->widget()));
+ touchPoint->setLastPos(item->d_ptr->genericMapFromScene(touchPoint->lastScenePos(), touchEvent->widget()));
+ }
+ sendEvent(item, touchEvent);
+}
+
+void QGraphicsScenePrivate::touchBeginEvent(QGraphicsSceneTouchEvent *touchEvent)
+{
+ Q_Q(QGraphicsScene);
+
+ // Ignore by default, unless we find a mouse grabber that accepts it.
+ touchEvent->ignore();
+
+ // Deliver to any existing mouse grabber.
+ if (!mouseGrabberItems.isEmpty()) {
+ // The event is ignored by default, but we disregard the event's
+ // accepted state after delivery; the mouse is grabbed, after all.
+ sendTouchEvent(touchEvent);
+ return;
+ }
+
+ // Start by determining the number of items at the current position.
+ // Reuse value from earlier calculations if possible.
+ if (cachedItemsUnderMouse.isEmpty()) {
+ QGraphicsSceneTouchEvent::TouchPoint *touchPoint = touchEvent->touchPoints().first();
+ // ### FIXME: should the itemsAtPosition() function support sub-pixel screenPos?
+ cachedItemsUnderMouse = itemsAtPosition(touchPoint->screenPos().toPoint(),
+ touchPoint->scenePos(),
+ touchEvent->widget());
+ }
+
+ // Update window activation.
+ QGraphicsWidget *newActiveWindow = windowForItem(cachedItemsUnderMouse.value(0));
+ if (newActiveWindow != activeWindow)
+ q->setActiveWindow(newActiveWindow);
+
+ // Set focus on the topmost enabled item that can take focus.
+ bool setFocus = false;
+ foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
+ if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
+ if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
+ setFocus = true;
+ if (item != q->focusItem())
+ q->setFocusItem(item, Qt::MouseFocusReason);
+ break;
+ }
+ }
+ }
+
+ // If nobody could take focus, clear it.
+ if (!stickyFocus && !setFocus)
+ q->setFocusItem(0, Qt::MouseFocusReason);
+
+ // Find a mouse grabber by sending touch events to all mouse grabber
+ // candidates one at a time, until the event is accepted. It's accepted by
+ // default, so the receiver has to explicitly ignore it for it to pass
+ // through.
+ foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
+ if (!item->acceptTouchEvents()) {
+ // Skip items that don't accept the touch events
+ continue;
+ }
+
+ grabMouse(item, /* implicit = */ true);
+ touchEvent->accept();
+
+ // check if the item we are sending to are disabled (before we send the event)
+ bool disabled = !item->isEnabled();
+ bool isWindow = item->isWindow();
+ sendTouchEvent(touchEvent);
+
+ bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.last() != item;
+ if (disabled) {
+ ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
+ break;
+ }
+ if (touchEvent->isAccepted()) {
+ lastMouseGrabberItem = item;
+ return;
+ }
+ ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
+
+ // Don't propagate through windows.
+ if (isWindow)
+ break;
+ }
+
+ // Is the event still ignored? Then the mouse press goes to the scene.
+ // Reset the mouse grabber, clear the selection, clear focus, and leave
+ // the event ignored so that it can propagate through the originating
+ // view.
+ if (!touchEvent->isAccepted()) {
+ clearMouseGrabber();
+
+ QGraphicsView *view = touchEvent->widget() ? qobject_cast<QGraphicsView *>(touchEvent->widget()->parentWidget()) : 0;
+ bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag;
+ if (!dontClearSelection) {
+ // Clear the selection if the originating view isn't in scroll
+ // hand drag mode. The view will clear the selection if no drag
+ // happened.
+ q->clearSelection();
+ }
+ }
+}
+
+void QGraphicsScenePrivate::touchUpdateEvent(QGraphicsSceneTouchEvent *touchEvent)
+{
+ if (mouseGrabberItems.isEmpty()) {
+ touchEvent->ignore();
+ return;
+ }
+
+ // Forward the event to the mouse grabber
+ sendTouchEvent(touchEvent);
+ touchEvent->accept();
+}
+
+void QGraphicsScenePrivate::touchEndEvent(QGraphicsSceneTouchEvent *touchEvent)
+{
+ if (mouseGrabberItems.isEmpty()) {
+ touchEvent->ignore();
+ return;
+ }
+
+ // Forward the event to the mouse grabber
+ sendTouchEvent(touchEvent);
+ touchEvent->accept();
+
+ // Reset the mouse grabber
+ if (!mouseGrabberItems.isEmpty()) {
+ lastMouseGrabberItem = mouseGrabberItems.last();
+ if (lastMouseGrabberItemHasImplicitMouseGrab)
+ mouseGrabberItems.last()->ungrabMouse();
+ } else {
+ lastMouseGrabberItem = 0;
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qgraphicsscene.cpp"
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 9ace725..de39205 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE
class QGraphicsView;
class QGraphicsWidget;
+class QGraphicsSceneTouchEvent;
class QGraphicsScenePrivate : public QObjectPrivate
{
@@ -266,6 +267,11 @@ public:
mutable QVector<QTransform> sceneTransformCache;
mutable QBitArray validTransforms;
mutable QVector<int> freeSceneTransformSlots;
+
+ void sendTouchEvent(QGraphicsSceneTouchEvent *touchEvent);
+ void touchBeginEvent(QGraphicsSceneTouchEvent *touchEvent);
+ void touchUpdateEvent(QGraphicsSceneTouchEvent *touchEvent);
+ void touchEndEvent(QGraphicsSceneTouchEvent *touchEvent);
};
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp
index b819c2c..3c9799b 100644
--- a/src/gui/graphicsview/qgraphicssceneevent.cpp
+++ b/src/gui/graphicsview/qgraphicssceneevent.cpp
@@ -76,14 +76,14 @@
received by the view (see
\l{QGraphicsSceneMouseEvent::}{lastScreenPos()},
\l{QGraphicsSceneMouseEvent::}{lastScenePos()}, and
- \l{QGraphicsSceneMouseEvent::}{lastPos()}).
+ \l{QGraphicsSceneMouseEvent::}{lastPos()}).
\sa QEvent
*/
/*!
\class QGraphicsSceneMouseEvent
- \brief The QGraphicsSceneMouseEvent class provides mouse events
+ \brief The QGraphicsSceneMouseEvent class provides mouse events
in the graphics view framework.
\since 4.2
\ingroup multimedia
@@ -106,7 +106,7 @@
/*!
\class QGraphicsSceneWheelEvent
- \brief The QGraphicsSceneWheelEvent class provides wheel events
+ \brief The QGraphicsSceneWheelEvent class provides wheel events
in the graphics view framework.
\brief The QGraphicsSceneWheelEvent class provides wheel events in the
graphics view framework.
@@ -157,7 +157,7 @@
/*!
\class QGraphicsSceneHoverEvent
- \brief The QGraphicsSceneHoverEvent class provides hover events
+ \brief The QGraphicsSceneHoverEvent class provides hover events
in the graphics view framework.
\since 4.2
\ingroup multimedia
@@ -173,7 +173,7 @@
/*!
\class QGraphicsSceneHelpEvent
- \brief The QGraphicsSceneHelpEvent class provides events when a
+ \brief The QGraphicsSceneHelpEvent class provides events when a
tooltip is requested.
\since 4.2
\ingroup multimedia
@@ -199,7 +199,7 @@
/*!
\class QGraphicsSceneDragDropEvent
\brief The QGraphicsSceneDragDropEvent class provides events for
- drag and drop in the graphics view framework.
+ drag and drop in the graphics view framework.
\since 4.2
\ingroup multimedia
\ingroup graphicsview-api
@@ -257,6 +257,37 @@
QGraphicsItem::ItemPositionHasChanged
*/
+/*!
+ \class QGraphicsSceneTouchEvent
+ \brief The QGraphicsSceneTouchEvent class provides touch events in the graphics view framework.
+ \since 4.6
+ \ingroup multimedia
+ \ingroup graphicsview-api
+
+ When a QGraphicsView receives a QTouchEvent, it translates it to a
+ QGraphicsSceneTouchEvent. The event is then forwarded to the
+ QGraphicsScene associated with the view.
+
+ The touchPoints() function returns a list of touch points for the
+ event. In addition to containing the item, scene, and screen
+ coordinates, each touch point also contains its starting and
+ previous coordinates.
+
+ \sa QTouchEvent
+*/
+
+/*!
+ \class QGraphicsSceneTouchEvent::TouchPoint
+ \brief The QGraphicsSceneTouchEvent::TouchPoint class represents a single touch point in a QGraphicsSceneTouchEvent.
+ \since 4.6
+ \ingroup multimedia
+ \ingroup graphicsview-api
+
+ Each touch point in a QGraphicsSceneTouchEvent has an id() and
+ state() in addition to current, starting, and previous coordinates
+ for the touch point in item, scene, and screen coordinates.
+*/
+
#include "qgraphicssceneevent.h"
#ifndef QT_NO_GRAPHICSVIEW
@@ -522,7 +553,7 @@ void QGraphicsSceneMouseEvent::setLastPos(const QPointF &pos)
}
/*!
- Returns the last recorded mouse cursor position in scene
+ Returns the last recorded mouse cursor position in scene
coordinates. The last recorded position is the position of
the previous mouse event received by the view that created
the event.
@@ -545,7 +576,7 @@ void QGraphicsSceneMouseEvent::setLastScenePos(const QPointF &pos)
}
/*!
- Returns the last recorded mouse cursor position in screen
+ Returns the last recorded mouse cursor position in screen
coordinates. The last recorded position is the position of
the previous mouse event received by the view that created
the event.
@@ -1275,7 +1306,7 @@ QGraphicsSceneDragDropEvent::~QGraphicsSceneDragDropEvent()
/*!
Returns the mouse position of the event relative to the
view that sent the event.
-
+
\sa QGraphicsView, screenPos(), scenePos()
*/
QPointF QGraphicsSceneDragDropEvent::pos() const
@@ -1373,7 +1404,7 @@ void QGraphicsSceneDragDropEvent::setButtons(Qt::MouseButtons buttons)
/*!
Returns the keyboard modifiers that were pressed when the drag
- and drop event was created.
+ and drop event was created.
\sa Qt::KeyboardModifiers
*/
@@ -1428,7 +1459,7 @@ void QGraphicsSceneDragDropEvent::setPossibleActions(Qt::DropActions actions)
The action must be one of the possible actions as defined by
\c possibleActions().
- \sa Qt::DropAction, possibleActions()
+ \sa Qt::DropAction, possibleActions()
*/
Qt::DropAction QGraphicsSceneDragDropEvent::proposedAction() const
@@ -1673,6 +1704,291 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos)
d->newPos = pos;
}
+class QGraphicsSceneTouchEventPrivate : public QGraphicsSceneEventPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsSceneTouchEvent)
+public:
+ inline QGraphicsSceneTouchEventPrivate()
+ : modifiers(Qt::NoModifier)
+ { }
+
+ QList<QGraphicsSceneTouchEvent::TouchPoint *> touchPoints;
+ Qt::KeyboardModifiers modifiers;
+};
+
+/*!
+ \internal
+
+ Constructs a generic QGraphicsSceneTouchEvent of type \a type.
+*/
+QGraphicsSceneTouchEvent::QGraphicsSceneTouchEvent(Type type)
+ : QGraphicsSceneEvent(*new QGraphicsSceneTouchEventPrivate, type)
+{ }
+
+/*!
+ Destroys the QGraphicsSceneTouchEvent.
+*/
+QGraphicsSceneTouchEvent::~QGraphicsSceneTouchEvent()
+{
+ Q_D(QGraphicsSceneTouchEvent);
+ qDeleteAll(d->touchPoints);
+}
+
+/*!
+ Returns the list of touch points for this event.
+
+ \sa QGraphicsSceneTouchEvent::TouchPoint
+*/
+const QList<QGraphicsSceneTouchEvent::TouchPoint *> &QGraphicsSceneTouchEvent::touchPoints() const
+{
+ Q_D(const QGraphicsSceneTouchEvent);
+ return d->touchPoints;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::setTouchPoints(const QList<QGraphicsSceneTouchEvent::TouchPoint *> &touchPoints)
+{
+ Q_D(QGraphicsSceneTouchEvent);
+ d->touchPoints = touchPoints;
+}
+
+/*!
+ Returns the keyboard modifiers in use at the time the event was
+ sent.
+*/
+Qt::KeyboardModifiers QGraphicsSceneTouchEvent::modifiers() const
+{
+ Q_D(const QGraphicsSceneTouchEvent);
+ return d->modifiers;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::setModifiers(Qt::KeyboardModifiers modifiers)
+{
+ Q_D(QGraphicsSceneTouchEvent);
+ d->modifiers = modifiers;
+}
+
+class QGraphicsSceneTouchEventTouchPointPrivate
+{
+public:
+ inline QGraphicsSceneTouchEventTouchPointPrivate()
+ : id(-1), state(Qt::TouchPointReleased), pressure(qreal(0.))
+ { }
+
+ int id;
+ Qt::TouchPointState state;
+ QPointF pos, startPos, lastPos;
+ QPointF scenePos, startScenePos, lastScenePos;
+ QPointF screenPos, startScreenPos, lastScreenPos;
+ qreal pressure;
+};
+
+/*! \internal
+
+ Constructs a new touch point for use in a QGraphicsSceneTouchEvent.
+*/
+QGraphicsSceneTouchEvent::TouchPoint::TouchPoint()
+ : d(new QGraphicsSceneTouchEventTouchPointPrivate)
+{
+}
+
+/*! \internal
+
+ Destroys the QGraphicsSceneTouchEvent::TouchPoint.
+*/
+QGraphicsSceneTouchEvent::TouchPoint::~TouchPoint()
+{
+ delete d;
+}
+
+/*!
+ Returns the identifier for this touch point.
+*/
+int QGraphicsSceneTouchEvent::TouchPoint::id() const
+{
+ return d->id;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setId(int id)
+{
+ d->id = id;
+}
+
+/*!
+ Returns the state of this touch point at the time the
+ QGraphicsSceneTouchEvent occurred.
+*/
+Qt::TouchPointState QGraphicsSceneTouchEvent::TouchPoint::state() const
+{
+ return d->state;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setState(Qt::TouchPointState state)
+{
+ d->state = state;
+}
+
+/*!
+ Returns the current position of this touch point in item coordinates.
+
+ \sa scenePos(), screenPos()
+*/
+QPointF QGraphicsSceneTouchEvent::TouchPoint::pos() const
+{
+ return d->pos;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setPos(const QPointF &pos)
+{
+ d->pos = pos;
+}
+
+/*!
+ Returns the starting position of this touch point in item coordinates.
+
+ \sa startScenePos(), startScreenPos()
+*/
+QPointF QGraphicsSceneTouchEvent::TouchPoint::startPos() const
+{
+ return d->startPos;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setStartPos(const QPointF &startPos)
+{
+ d->startPos = startPos;
+}
+
+/*!
+ Returns the previous position of this touch point in item coordinates.
+
+ \sa lastScenePos(), lastScreenPos()
+*/
+QPointF QGraphicsSceneTouchEvent::TouchPoint::lastPos() const
+{
+ return d->lastPos;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setLastPos(const QPointF &lastPos)
+{
+ d->lastPos = lastPos;
+}
+
+/*!
+ Returns the current position of this touch point in scene coordinates.
+
+ \sa pos(), screenPos()
+*/
+QPointF QGraphicsSceneTouchEvent::TouchPoint::scenePos() const
+{
+ return d->scenePos;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos)
+{
+ d->scenePos = scenePos;
+}
+
+/*!
+ Returns the starting position of this touch point in scene coordinates.
+
+ \sa startPos(), startScreenPos()
+*/
+QPointF QGraphicsSceneTouchEvent::TouchPoint::startScenePos() const
+{
+ return d->startScenePos;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setStartScenePos(const QPointF &startScenePos)
+{
+ d->startScenePos = startScenePos;
+}
+
+/*!
+ Returns the previous position of this touch point in scene coordinates.
+
+ \sa lastPos(), lastScreenPos()
+*/
+QPointF QGraphicsSceneTouchEvent::TouchPoint::lastScenePos() const
+{
+ return d->lastScenePos;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setLastScenePos(const QPointF &lastScenePos)
+{
+ d->lastScenePos = lastScenePos;
+}
+
+/*!
+ Returns the current position of this touch point in screen coordinates.
+
+ \sa pos(), scenePos()
+*/
+QPointF QGraphicsSceneTouchEvent::TouchPoint::screenPos() const
+{
+ return d->screenPos;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos)
+{
+ d->screenPos = screenPos;
+}
+
+/*!
+ Returns the starting position of this touch point in screen coordinates.
+
+ \sa startPos(), startScenePos()
+*/
+QPointF QGraphicsSceneTouchEvent::TouchPoint::startScreenPos() const
+{
+ return d->startScreenPos;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setStartScreenPos(const QPointF &startScreenPos)
+{
+ d->startScreenPos = startScreenPos;
+}
+
+/*!
+ Returns the previous position of this touch point in screen coordinates.
+
+ \sa lastPos(), lastScenePos()
+*/
+QPointF QGraphicsSceneTouchEvent::TouchPoint::lastScreenPos() const
+{
+ return d->lastScreenPos;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setLastScreenPos(const QPointF &lastScreenPos)
+{
+ d->lastScreenPos = lastScreenPos;
+}
+
+/*!
+ Returns the pressure of this touch point.
+*/
+qreal QGraphicsSceneTouchEvent::TouchPoint::pressure() const
+{
+ return d->pressure;
+}
+
+/*! \internal */
+void QGraphicsSceneTouchEvent::TouchPoint::setPressure(qreal pressure)
+{
+ d->pressure = pressure;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h
index be50e96..8ae3a99 100644
--- a/src/gui/graphicsview/qgraphicssceneevent.h
+++ b/src/gui/graphicsview/qgraphicssceneevent.h
@@ -302,6 +302,70 @@ public:
void setNewPos(const QPointF &pos);
};
+class QGraphicsSceneTouchEventPrivate;
+class QGraphicsSceneTouchEventTouchPointPrivate;
+class Q_GUI_EXPORT QGraphicsSceneTouchEvent : public QGraphicsSceneEvent
+{
+public:
+ QGraphicsSceneTouchEvent(Type type = None);
+ ~QGraphicsSceneTouchEvent();
+
+ class Q_GUI_EXPORT TouchPoint
+ {
+ public:
+ TouchPoint();
+ ~TouchPoint();
+
+ int id() const;
+ void setId(int id);
+
+ Qt::TouchPointState state() const;
+ void setState(Qt::TouchPointState state);
+
+ QPointF pos() const;
+ void setPos(const QPointF &pos);
+
+ QPointF startPos() const;
+ void setStartPos(const QPointF &startPos);
+
+ QPointF lastPos() const;
+ void setLastPos(const QPointF &lastPos);
+
+ QPointF scenePos() const;
+ void setScenePos(const QPointF &scenePos);
+
+ QPointF startScenePos() const;
+ void setStartScenePos(const QPointF &startScenePos);
+
+ QPointF lastScenePos() const;
+ void setLastScenePos(const QPointF &lastScenePos);
+
+ QPointF screenPos() const;
+ void setScreenPos(const QPointF &screenPos);
+
+ QPointF startScreenPos() const;
+ void setStartScreenPos(const QPointF &startScreenPos);
+
+ QPointF lastScreenPos() const;
+ void setLastScreenPos(const QPointF &lastScreenPos);
+
+ qreal pressure() const; // 0.0 -> 1.0
+ void setPressure(qreal pressure);
+
+ private:
+ QGraphicsSceneTouchEventTouchPointPrivate *d;
+ };
+
+ const QList<TouchPoint *> &touchPoints() const;
+ void setTouchPoints(const QList<TouchPoint *> &touchPoints);
+
+ Qt::KeyboardModifiers modifiers() const;
+ void setModifiers(Qt::KeyboardModifiers modifiers);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsSceneTouchEvent);
+};
+
#endif // QT_NO_GRAPHICSVIEW
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 2876016..1aaaab9 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -2940,6 +2940,28 @@ bool QGraphicsView::viewportEvent(QEvent *event)
d->scene->d_func()->updateAll = false;
}
break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ {
+ if (!isEnabled())
+ return false;
+ QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
+ switch (touchEvent->type()) {
+ case QEvent::TouchBegin:
+ d->touchBeginEvent(touchEvent);
+ break;
+ case QEvent::TouchUpdate:
+ d->touchUpdateEvent(touchEvent);
+ break;
+ case QEvent::TouchEnd:
+ d->touchEndEvent(touchEvent);
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
default:
break;
}
@@ -3878,6 +3900,90 @@ void QGraphicsView::resetTransform()
setTransform(QTransform());
}
+static void qt_convertTouchEventToGraphicsSceneTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *originalEvent, QGraphicsSceneTouchEvent *touchEvent)
+{
+ QList<QTouchEvent::TouchPoint *> originalTouchPoints = originalEvent->touchPoints();
+ QList<QGraphicsSceneTouchEvent::TouchPoint *> touchPoints;
+ for (int i = 0; i < originalTouchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint *originalTouchPoint = originalTouchPoints.at(i);
+
+ QGraphicsSceneTouchEvent::TouchPoint *touchPoint = new QGraphicsSceneTouchEvent::TouchPoint();
+ touchPoint->setId(originalTouchPoint->id());
+ touchPoint->setState(originalTouchPoint->state());
+ // the scene will set the pos before delivering to an item
+ touchPoint->setScenePos(d->mapToScene(originalTouchPoint->pos()));
+ touchPoint->setScreenPos(originalTouchPoint->globalPos());
+ // the scene will set the startPos before delivering to an item
+ touchPoint->setStartScenePos(d->mapToScene(originalTouchPoint->startPos()));
+ touchPoint->setStartScreenPos(originalTouchPoint->startGlobalPos());
+ // the scene will set the lastPos before delivering to an item
+ touchPoint->setLastScenePos(d->mapToScene(originalTouchPoint->lastPos()));
+ touchPoint->setLastScreenPos(originalTouchPoint->lastGlobalPos());
+ touchPoint->setPressure(originalTouchPoint->pressure());
+
+ touchPoints.append(touchPoint);
+ }
+
+ touchEvent->setTouchPoints(touchPoints);
+ touchEvent->setModifiers(originalEvent->modifiers());
+}
+
+QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const
+{
+ QPointF p = point;
+ p.rx() += horizontalScroll();
+ p.ry() += verticalScroll();
+ return identityMatrix ? p : matrix.inverted().map(p);
+}
+
+void QGraphicsViewPrivate::touchBeginEvent(QTouchEvent *event)
+{
+ Q_Q(QGraphicsView);
+
+ if (!scene || !sceneInteractionAllowed)
+ return;
+
+ // Convert and deliver the touch event to the scene.
+ QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchBegin);
+ touchEvent.setWidget(q->viewport());
+ qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent);
+ touchEvent.setAccepted(false);
+ QApplication::sendEvent(scene, &touchEvent);
+ event->setAccepted(touchEvent.isAccepted());
+}
+
+void QGraphicsViewPrivate::touchUpdateEvent(QTouchEvent *event)
+{
+ Q_Q(QGraphicsView);
+
+ if (!scene || !sceneInteractionAllowed)
+ return;
+
+ // Convert and deliver the touch event to the scene.
+ QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchUpdate);
+ touchEvent.setWidget(q->viewport());
+ qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent);
+ touchEvent.setAccepted(false);
+ QApplication::sendEvent(scene, &touchEvent);
+ event->setAccepted(touchEvent.isAccepted());
+}
+
+void QGraphicsViewPrivate::touchEndEvent(QTouchEvent *event)
+{
+ Q_Q(QGraphicsView);
+
+ if (!scene || !sceneInteractionAllowed)
+ return;
+
+ // Convert and deliver the touch event to the scene.
+ QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchEnd);
+ touchEvent.setWidget(q->viewport());
+ qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent);
+ touchEvent.setAccepted(false);
+ QApplication::sendEvent(scene, &touchEvent);
+ event->setAccepted(touchEvent.isAccepted());
+}
+
QT_END_NAMESPACE
#include "moc_qgraphicsview.cpp"
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index a76279e..abab921 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -181,6 +181,11 @@ public:
const QTransform &worldTransform,
bool allItems,
const QRegion &exposedRegion) const;
+
+ QPointF mapToScene(const QPointF &point) const;
+ void touchBeginEvent(QTouchEvent *event);
+ void touchUpdateEvent(QTouchEvent *event);
+ void touchEndEvent(QTouchEvent *event);
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index b9ebf55..1f4e1fe 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -85,6 +85,7 @@
#include <stdlib.h>
#include "qapplication_p.h"
+#include "qevent_p.h"
#include "qwidget_p.h"
#include "qapplication.h"
@@ -3700,19 +3701,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QPoint relpos = mouse->pos();
if (e->spontaneous()) {
-
if (e->type() == QEvent::MouseButtonPress) {
- QWidget *fw = w;
- while (fw) {
- if (fw->isEnabled()
- && QApplicationPrivate::shouldSetFocus(fw, Qt::ClickFocus)) {
- fw->setFocus(Qt::MouseFocusReason);
- break;
- }
- if (fw->isWindow())
- break;
- fw = fw->parentWidget();
- }
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
+ Qt::ClickFocus,
+ Qt::MouseFocusReason);
}
if (e->type() == QEvent::MouseMove && mouse->buttons() == 0) {
@@ -3794,17 +3786,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
bool eventAccepted = wheel->isAccepted();
if (e->spontaneous()) {
- QWidget *fw = w;
- while (fw) {
- if (fw->isEnabled()
- && QApplicationPrivate::shouldSetFocus(fw, Qt::WheelFocus)) {
- fw->setFocus(Qt::MouseFocusReason);
- break;
- }
- if (fw->isWindow())
- break;
- fw = fw->parentWidget();
- }
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
+ Qt::WheelFocus,
+ Qt::MouseFocusReason);
}
while (w) {
@@ -4009,7 +3993,49 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
}
break;
#endif
+ case QEvent::TouchBegin:
+ // Note: TouchUpdate and TouchEnd events are sent to d->currentMultitouchWidget and never propagated
+ {
+ QWidget *widget = static_cast<QWidget *>(receiver);
+ QWidget *origin = widget;
+ QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e);
+ bool eventAccepted = touchEvent->isAccepted();
+
+ if (widget->testAttribute(Qt::WA_AcceptTouchEvents) && e->spontaneous()) {
+ // give the widget focus if the focus policy allows it
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget,
+ Qt::ClickFocus,
+ Qt::MouseFocusReason);
+ }
+ while (widget) {
+ // first, try to deliver the touch event
+ touchEvent->ignore();
+ res = widget->testAttribute(Qt::WA_AcceptTouchEvents)
+ && d->notify_helper(widget, touchEvent);
+ eventAccepted = touchEvent->isAccepted();
+ widget->setAttribute(Qt::WA_AcceptedTouchBeginEvent, res && eventAccepted);
+ touchEvent->spont = false;
+ if (res && eventAccepted) {
+ // the first widget to accept the TouchBegin gets an implicit grab.
+ for (int i = 0; i < touchEvent->_touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint *touchPoint = touchEvent->_touchPoints.at(i);
+ touchPoint->d->widget = widget;
+ }
+ if (origin != widget)
+ origin->d_func()->currentTouchPoints.clear();
+ widget->d_func()->currentTouchPoints = touchEvent->_touchPoints;
+ break;
+ } else if (widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) {
+ break;
+ }
+ widget = widget->parentWidget();
+ d->updateTouchPointsForWidget(widget, touchEvent);
+ }
+
+ touchEvent->setAccepted(eventAccepted);
+ break;
+ }
default:
res = d->notify_helper(receiver, e);
break;
@@ -4976,6 +5002,23 @@ Qt::LayoutDirection QApplication::keyboardInputDirection()
return qt_keymapper_private()->keyboardInputDirection;
}
+void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget,
+ Qt::FocusPolicy focusPolicy,
+ Qt::FocusReason focusReason)
+{
+ QWidget *focusWidget = widget;
+ while (focusWidget) {
+ if (focusWidget->isEnabled()
+ && QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) {
+ focusWidget->setFocus(focusReason);
+ break;
+ }
+ if (focusWidget->isWindow())
+ break;
+ focusWidget = focusWidget->parentWidget();
+ }
+}
+
bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
{
QWidget *f = w;
@@ -5120,6 +5163,19 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
This normally takes some time. Does nothing on other platforms.
*/
+void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
+{
+ for (int i = 0; i < touchEvent->_touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint *touchPoint = touchEvent->_touchPoints.at(i);
+
+ // preserve the sub-pixel resolution
+ const QPointF delta = touchPoint->d->globalPos - touchPoint->d->globalPos.toPoint();
+ touchPoint->d->pos = widget->mapFromGlobal(touchPoint->d->globalPos.toPoint()) + delta;
+ touchPoint->d->startPos = widget->mapFromGlobal(touchPoint->d->startGlobalPos.toPoint()) + delta;
+ touchPoint->d->lastPos = widget->mapFromGlobal(touchPoint->d->lastGlobalPos.toPoint()) + delta;
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 7e97418..1a2bad2 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -55,6 +55,7 @@
//
#include "QtGui/qapplication.h"
+#include "QtGui/qevent.h"
#include "QtGui/qfont.h"
#include "QtGui/qcursor.h"
#include "QtGui/qregion.h"
@@ -77,10 +78,7 @@ class QClipboard;
class QGraphicsScene;
class QGraphicsSystem;
class QInputContext;
-class QKeyEvent;
-class QMouseEvent;
class QObject;
-class QWheelEvent;
class QWidget;
extern bool qt_is_gui_used;
@@ -189,6 +187,12 @@ extern "C" {
}
#endif
+#if defined(Q_WS_WIN)
+typedef BOOL (WINAPI *qt_RegisterTouchWindowPtr)(HWND, ULONG);
+typedef BOOL (WINAPI *qt_GetTouchInputInfoPtr)(HANDLE, UINT, PVOID, int);
+typedef BOOL (WINAPI *qt_CloseTouchInputHandlePtr)(HANDLE);
+#endif
+
class QScopedLoopLevelCounter
{
QThreadData *threadData;
@@ -424,12 +428,35 @@ public:
void sendSyntheticEnterLeave(QWidget *widget);
#endif
+ static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
+
+#if defined(Q_WS_WIN)
+ static qt_RegisterTouchWindowPtr RegisterTouchWindow;
+ static qt_GetTouchInputInfoPtr GetTouchInputInfo;
+ static qt_CloseTouchInputHandlePtr CloseTouchInputHandle;
+
+ QMap<DWORD, int> touchInputIDToTouchPointID;
+ QVector<QTouchEvent::TouchPoint *> appAllTouchPoints;
+ QList<QTouchEvent::TouchPoint *> appCurrentTouchPoints;
+
+ void initializeMultitouch();
+ static QTouchEvent::TouchPoint *findClosestTouchPoint(const QList<QTouchEvent::TouchPoint *> &activeTouchPoints,
+ const QPointF &pos);
+ QEvent::Type appendTouchPoint(QTouchEvent::TouchPoint *touchPoint);
+ QEvent::Type removeTouchPoint(QTouchEvent::TouchPoint *touchPoint);
+ bool translateTouchEvent(const MSG &msg);
+#endif
+
private:
#ifdef Q_WS_QWS
QMap<const QScreen*, QRect> maxWindowRects;
#endif
static QApplicationPrivate *self;
+
+ static void giveFocusAccordingToFocusPolicy(QWidget *w,
+ Qt::FocusPolicy focusPolicy,
+ Qt::FocusReason focusReason);
static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy);
};
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 6237657..723a3b4 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -88,6 +88,7 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
#include "qdebug.h"
#include <private/qkeymapper_p.h>
#include <private/qlocale_p.h>
+#include "qevent_p.h"
//#define ALIEN_DEBUG
@@ -112,6 +113,39 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
# include <winable.h>
#endif
+#ifndef WM_TOUCHMOVE
+
+# define WM_TOUCHMOVE 0x0240
+# define WM_TOUCHDOWN 0x0241
+# define WM_TOUCHUP 0x0242
+
+# define TOUCHEVENTF_MOVE 0x0001
+# define TOUCHEVENTF_DOWN 0x0002
+# define TOUCHEVENTF_UP 0x0004
+# define TOUCHEVENTF_INRANGE 0x0008
+# define TOUCHEVENTF_PRIMARY 0x0010
+# define TOUCHEVENTF_NOCOALESCE 0x0020
+# define TOUCHEVENTF_PEN 0x0040
+
+# define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001
+# define TOUCHINPUTMASKF_EXTRAINFO 0x0002
+# define TOUCHINPUTMASKF_CONTACTAREA 0x0004
+
+typedef struct tagTOUCHINPUT
+{
+ LONG x;
+ LONG y;
+ HANDLE hSource;
+ DWORD dwID;
+ DWORD dwFlags;
+ DWORD dwMask;
+ DWORD dwTime;
+ ULONG_PTR dwExtraInfo;
+ DWORD cxContact;
+ DWORD cyContact;
+} TOUCHINPUT, *PTOUCHINPUT;
+
+#endif
#ifndef FLASHW_STOP
typedef struct {
@@ -853,6 +887,8 @@ void qt_init(QApplicationPrivate *priv, int)
if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect)
ptrUpdateLayeredWindowIndirect = qt_updateLayeredWindowIndirect;
#endif
+
+ priv->initializeMultitouch();
}
/*****************************************************************************
@@ -1716,6 +1752,11 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
result = widget->translateWheelEvent(msg);
} else {
switch (message) {
+ case WM_TOUCHMOVE:
+ case WM_TOUCHDOWN:
+ case WM_TOUCHUP:
+ result = getQApplicationPrivateInternal()->translateTouchEvent(msg);
+ break;
case WM_KEYDOWN: // keyboard event
case WM_SYSKEYDOWN:
qt_keymapper_private()->updateKeyMap(msg);
@@ -3956,4 +3997,223 @@ void QSessionManager::cancel()
#endif //QT_NO_SESSIONMANAGER
+qt_RegisterTouchWindowPtr QApplicationPrivate::RegisterTouchWindow = 0;
+qt_GetTouchInputInfoPtr QApplicationPrivate::GetTouchInputInfo = 0;
+qt_CloseTouchInputHandlePtr QApplicationPrivate::CloseTouchInputHandle = 0;
+
+void QApplicationPrivate::initializeMultitouch()
+{
+ QLibrary library(QLatin1String("user32"));
+ RegisterTouchWindow = static_cast<qt_RegisterTouchWindowPtr>(library.resolve("RegisterTouchWindow"));
+ GetTouchInputInfo = static_cast<qt_GetTouchInputInfoPtr>(library.resolve("GetTouchInputInfo"));
+ CloseTouchInputHandle = static_cast<qt_CloseTouchInputHandlePtr>(library.resolve("CloseTouchInputHandle"));
+
+ touchInputIDToTouchPointID.clear();
+ appAllTouchPoints.clear();
+}
+
+QTouchEvent::TouchPoint *QApplicationPrivate::findClosestTouchPoint(const QList<QTouchEvent::TouchPoint *> &appActiveTouchPoints,
+ const QPointF &pos)
+{
+ QTouchEvent::TouchPoint *closestTouchPoint = 0;
+ qreal closestDistance;
+ for (int i = 0; i < appActiveTouchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint *touchPoint = appActiveTouchPoints.at(i);
+ qreal distance = QLineF(pos, touchPoint->d->globalPos).length();
+ if (!closestTouchPoint || distance < closestDistance) {
+ closestTouchPoint = touchPoint;
+ closestDistance = distance;
+ }
+ }
+ return closestTouchPoint;
+}
+
+QEvent::Type QApplicationPrivate::appendTouchPoint(QTouchEvent::TouchPoint *touchPoint)
+{
+ QWidget *widget = touchPoint->d->widget;
+ QEvent::Type eventType = widget->d_func()->currentTouchPoints.isEmpty()
+ ? QEvent::TouchBegin
+ : QEvent::TouchUpdate;
+
+ // insort touch point (for the app)
+ int at = 0;
+ for (; at < appCurrentTouchPoints.count(); ++at) {
+ if (appCurrentTouchPoints.at(at)->id() > touchPoint->id())
+ break;
+ }
+ appCurrentTouchPoints.insert(at, touchPoint);
+ // again, for the widget's currentTouchPoints
+ for (at = 0; at < widget->d_func()->currentTouchPoints.count(); ++at) {
+ if (widget->d_func()->currentTouchPoints.at(at)->id() > touchPoint->id())
+ break;
+ }
+ widget->d_func()->currentTouchPoints.insert(at, touchPoint);
+
+ if (appCurrentTouchPoints.count() > appAllTouchPoints.count()) {
+ qFatal("Qt: INTERNAL ERROR: appCurrentTouchPoints.count() (%d) > appAllTouchPoints.count() (%d)",
+ appCurrentTouchPoints.count(),
+ appAllTouchPoints.count());
+ }
+
+ return eventType;
+}
+
+QEvent::Type QApplicationPrivate::removeTouchPoint(QTouchEvent::TouchPoint *touchPoint)
+{
+ QWidget *widget = touchPoint->d->widget;
+
+ // remove touch point from all known touch points
+ for (int i = qMin(appCurrentTouchPoints.count() - 1, touchPoint->id()); i >= 0; --i) {
+ if (appCurrentTouchPoints.at(i) == touchPoint) {
+ appCurrentTouchPoints.removeAt(i);
+ break;
+ }
+ }
+ // again, for the widget's currentTouchPoints
+ for (int i = qMin(widget->d_func()->currentTouchPoints.count() - 1, touchPoint->id()); i >= 0; --i) {
+ if (widget->d_func()->currentTouchPoints.at(i) == touchPoint) {
+ widget->d_func()->currentTouchPoints.removeAt(i);
+ break;
+ }
+ }
+
+ return widget->d_func()->currentTouchPoints.isEmpty() ? QEvent::TouchEnd : QEvent::TouchUpdate;
+}
+
+bool QApplicationPrivate::translateTouchEvent(const MSG &msg)
+{
+ Q_Q(QApplication);
+
+ QWidget *widgetForHwnd = QWidget::find(msg.hwnd);
+ if (!widgetForHwnd)
+ return false;
+
+ QList<QTouchEvent::TouchPoint *> appActiveTouchPoints = appCurrentTouchPoints;
+
+ QHash<QWidget *, QTouchEvent> widgetsNeedingEvents;
+ QVector<TOUCHINPUT> winTouchInputs(msg.wParam);
+ memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count());
+ QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT));
+ for (int i = 0; i < winTouchInputs.count(); ++i) {
+ const TOUCHINPUT &touchInput = winTouchInputs.at(i);
+
+ int touchPointID = touchInputIDToTouchPointID.value(touchInput.dwID, -1);
+ if (touchPointID == -1) {
+ touchPointID = touchInputIDToTouchPointID.count();
+ touchInputIDToTouchPointID.insert(touchInput.dwID, touchPointID);
+ }
+
+ if (appAllTouchPoints.count() <= touchPointID)
+ appAllTouchPoints.resize(touchPointID + 1);
+
+ QTouchEvent::TouchPoint *touchPoint = appAllTouchPoints.at(touchPointID);
+ if (!touchPoint)
+ touchPoint = appAllTouchPoints[touchPointID] = new QTouchEvent::TouchPoint(touchPointID);
+
+ // update state
+ bool down = touchPoint->d->state != Qt::TouchPointReleased;
+ QPointF globalPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.));
+ QEvent::Type eventType = QEvent::None;
+ QList<QTouchEvent::TouchPoint *> activeTouchPoints;
+ if (!down && (touchInput.dwFlags & TOUCHEVENTF_DOWN)) {
+ // determine which widget this event will go to
+ QWidget *w = widgetForHwnd->childAt(widgetForHwnd->mapFromGlobal(globalPos.toPoint()));
+ if (!w)
+ w = widgetForHwnd;
+
+ QTouchEvent::TouchPoint *closestTouchPoint = findClosestTouchPoint(appActiveTouchPoints, globalPos);
+ if (closestTouchPoint
+ && (w->isAncestorOf(closestTouchPoint->d->widget)
+ || closestTouchPoint->d->widget->isAncestorOf(w))) {
+ w = closestTouchPoint->d->widget;
+ }
+ touchPoint->d->widget = w;
+
+ eventType = appendTouchPoint(touchPoint);
+ // make sure new points are added to activeTouchPoints as well
+ appActiveTouchPoints = appCurrentTouchPoints;
+ activeTouchPoints = w->d_func()->currentTouchPoints;
+
+ touchPoint->d->state = Qt::TouchPointPressed;
+ touchPoint->d->globalPos
+ = touchPoint->d->startGlobalPos
+ = touchPoint->d->lastGlobalPos
+ = globalPos;
+ touchPoint->d->pressure = qreal(1.);
+ } else if (down && (touchInput.dwFlags & TOUCHEVENTF_UP)) {
+ QWidget *w = touchPoint->d->widget;
+ appActiveTouchPoints = appCurrentTouchPoints;
+ activeTouchPoints = w->d_func()->currentTouchPoints;
+ eventType = removeTouchPoint(touchPoint);
+
+ touchPoint->d->state = Qt::TouchPointReleased;
+ touchPoint->d->lastGlobalPos = touchPoint->d->globalPos;
+ touchPoint->d->globalPos = globalPos;
+ touchPoint->d->pressure = qreal(0.);
+ } else if (down) {
+ QWidget *w = touchPoint->d->widget;
+ appActiveTouchPoints = appCurrentTouchPoints;
+ activeTouchPoints = w->d_func()->currentTouchPoints;
+ eventType = QEvent::TouchUpdate;
+ touchPoint->d->state = globalPos == touchPoint->d->globalPos
+ ? Qt::TouchPointStationary
+ : Qt::TouchPointMoved;
+ touchPoint->d->lastGlobalPos = touchPoint->d->globalPos;
+ touchPoint->d->globalPos = globalPos;
+ // pressure should still be 1.
+ }
+ Q_ASSERT(eventType != QEvent::None);
+
+ if (touchPoint->d->state != Qt::TouchPointStationary) {
+ widgetsNeedingEvents.insert(touchPoint->d->widget,
+ QTouchEvent(eventType, q->keyboardModifiers(), activeTouchPoints));
+ }
+ }
+ QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam);
+
+ if (widgetsNeedingEvents.isEmpty())
+ return false;
+
+ bool returnValue = false;
+ qt_tabletChokeMouse = false;
+
+ QHash<QWidget *, QTouchEvent>::ConstIterator it = widgetsNeedingEvents.constBegin();
+ const QHash<QWidget *, QTouchEvent>::ConstIterator end = widgetsNeedingEvents.constEnd();
+ for (; it != end; ++it) {
+ QWidget *widget = it.key();
+ if (!QApplicationPrivate::tryModalHelper(widget, 0))
+ continue;
+
+ QTouchEvent touchEvent = it.value();
+ updateTouchPointsForWidget(widget, &touchEvent);
+
+ switch (touchEvent.type()) {
+ case QEvent::TouchBegin:
+ {
+ // if the TouchBegin handler recurses, we assume that means the event
+ // has been implicitly accepted and continue to send touch events
+ widget->setAttribute(Qt::WA_AcceptedTouchBeginEvent);
+ bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent)
+ && touchEvent.isAccepted();
+ returnValue = returnValue || (qt_tabletChokeMouse = qt_tabletChokeMouse || res);
+ break;
+ }
+ case QEvent::TouchEnd:
+ if (!widget->d_func()->currentTouchPoints.isEmpty()) {
+ qFatal("Qt: INTERNAL ERROR, the widget's currentTouchPoints should be empty!");
+ }
+ // fall-through intended
+ default:
+ if (widget->testAttribute(Qt::WA_AcceptedTouchBeginEvent)) {
+ (void) QApplication::sendSpontaneousEvent(widget, &touchEvent);
+ qt_tabletChokeMouse = true;
+ }
+ returnValue = returnValue || qt_tabletChokeMouse;
+ break;
+ }
+ }
+
+ return returnValue;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 8c7e47d..d571212 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3506,4 +3506,168 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar)
#endif
+/*! \class QTouchEvent
+ \brief The QTouchEvent class contains parameters that describe a touch event
+.
+ \since 4.6
+ \ingroup events
+
+ Touch events occur when pressing, releasing, or moving one or more
+ touch points on a touch device (such as a touch-screen or
+ track-pad), and if the widget has the Qt::WA_AcceptTouchEvents
+ attribute.
+
+ Like QMouseEvent, Qt automatically grabs the touch device on the
+ first press inside a widget; the widget will receive all touch
+ events until the last touch point is released.
+
+ A touch event contains a special accept flag that indicates
+ whether the receiver wants the event. By default, the event is
+ ignored. You should call accept() if the touch event is handled by
+ your widget. A touch event is propagated up the parent widget
+ chain until a widget accepts it with accept(), or an event filter
+ consumes it. If the touch event is neither accepted nor consumed,
+ then mouse events are simulated from the state of the first touch
+ point.
+
+ All touch events are of type QEvent::Touch. The touchPoints()
+ function returns a list of all touch points contained in the
+ event. Information about each touch point can be retreived using
+ the QTouchEvent::TouchPoint class.
+
+ The Qt::TouchPointState enum describes the different states that a
+ touch point may have.
+
+ QTouchEvent::TouchPoint Qt::TouchPointState Qt::WA_AcceptTouchEvents
+*/
+
+/*! \enum Qt::TouchPointState
+ \since 4.6
+
+ This enum represents the state of a touch point at the time the
+ QTouchEvent occurred.
+
+ \value TouchPointPressed The touch point is now pressed.
+ \value TouchPointMoved The touch point moved.
+ \value TouchPointStationary The touch point did not move.
+ \value TouchPointReleased The touch point was released.
+*/
+
+/*! \class QTouchEvent::TouchPoint
+ \brief The QTouchEvent::TouchPoint class provide information about a touch point in a QTouchEvent.
+ \since 4.6
+*/
+
+/*!
+ Constructs a QTouchEvent with the given \a type and \a
+ touchPoints. The \a modifiers are the current keyboard modifiers
+ at the time of the event.
+*/
+QTouchEvent::QTouchEvent(QEvent::Type type,
+ Qt::KeyboardModifiers modifiers,
+ const QList<TouchPoint *> &touchPoints)
+ : QInputEvent(type, modifiers), _touchPoints(touchPoints)
+{ }
+
+/*! \fn const QList<QTouchEvent::TouchPoint *> &QTouchEvent::touchPoints() const
+
+ Returns the list of touch points contained in the touch event.
+*/
+
+/*! \internal
+
+ Constructs a QTouchEvent::TouchPoint for use in a QTouchEvent.
+*/
+QTouchEvent::TouchPoint::TouchPoint(int id)
+ : d(new QTouchEventTouchPointPrivate(id))
+{ }
+
+/*! \internal
+
+ Destroys the QTouchEvent::TouchPoint.
+*/
+QTouchEvent::TouchPoint::~TouchPoint()
+{
+ delete d;
+}
+
+/*!
+ Returns the id number of this touch point. Id numbers are
+ sequential, starting at zero, meaning the first touch point has id
+ 0, the second has id 1, and so on...
+*/
+int QTouchEvent::TouchPoint::id() const
+{
+ return d->id;
+}
+
+/*!
+ Returns the current state of this touch point.
+*/
+Qt::TouchPointState QTouchEvent::TouchPoint::state() const
+{
+ return d->state;
+}
+
+/*!
+ Returns the position of this touch point, relative to the widget
+ that received the event.
+*/
+const QPointF &QTouchEvent::TouchPoint::pos() const
+{
+ return d->pos;
+}
+
+/*!
+ Returns the starting position of this touch point, relative to the
+ widget that received the event.
+*/
+const QPointF &QTouchEvent::TouchPoint::startPos() const
+{
+ return d->startPos;
+}
+
+/*!
+ Returns the position of this touch point from the previous touch
+ event, relative to the widget that received the event.
+*/
+const QPointF &QTouchEvent::TouchPoint::lastPos() const
+{
+ return d->lastPos;
+}
+
+/*!
+ Returns the global position of this touch point.
+*/
+const QPointF &QTouchEvent::TouchPoint::globalPos() const
+{
+ return d->globalPos;
+}
+
+/*!
+ Returns the global starting position of this touch point.
+*/
+const QPointF &QTouchEvent::TouchPoint::startGlobalPos() const
+{
+ return d->startGlobalPos;
+}
+
+/*!
+ Returns the global position of this touch point from the previous
+ touch event.
+*/
+const QPointF &QTouchEvent::TouchPoint::lastGlobalPos() const
+{
+ return d->lastGlobalPos;
+}
+
+/*!
+ Returns the pressure of this touch point. The return value is in
+ the range 0.0 to 1.0.
+*/
+qreal QTouchEvent::TouchPoint::pressure() const
+{
+ return d->pressure;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 449730d..e9a1386 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -719,6 +719,51 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ?
inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);}
#endif // QT_NO_SHORTCUT
+class QTouchEventTouchPointPrivate;
+class Q_GUI_EXPORT QTouchEvent : public QInputEvent
+{
+public:
+ class Q_GUI_EXPORT TouchPoint
+ {
+ public:
+ TouchPoint(int id = -1);
+ ~TouchPoint();
+
+ int id() const;
+
+ Qt::TouchPointState state() const;
+
+ const QPointF &pos() const;
+ const QPointF &startPos() const;
+ const QPointF &lastPos() const;
+
+ const QPointF &globalPos() const;
+ const QPointF &startGlobalPos() const;
+ const QPointF &lastGlobalPos() const;
+
+ qreal pressure() const; // 0.0 -> 1.0
+
+ private:
+ QTouchEventTouchPointPrivate *d;
+
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ };
+
+ QTouchEvent(QEvent::Type type,
+ Qt::KeyboardModifiers modifiers,
+ const QList<TouchPoint *> &touchPoints);
+
+ inline const QList<TouchPoint *> &touchPoints() const { return _touchPoints;
+ }
+
+protected:
+ QList<TouchPoint *> _touchPoints;
+
+ friend class QApplication;
+ friend class QApplicationPrivate;
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 8e762d6..8623c66 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -89,6 +89,23 @@ protected:
friend class QMouseEvent;
};
+class QTouchEventTouchPointPrivate
+{
+public:
+ inline QTouchEventTouchPointPrivate(int id)
+ : id(id),
+ state(Qt::TouchPointReleased),
+ pressure(qreal(-1.))
+ { }
+
+ QPointer<QWidget> widget;
+ int id;
+ Qt::TouchPointState state;
+ QPointF pos, startPos, lastPos;
+ QPointF globalPos, startGlobalPos, lastGlobalPos;
+ qreal pressure;
+};
+
QT_END_NAMESPACE
#endif // QEVENT_P_H
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index cbf9585..968a423 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -7525,6 +7525,9 @@ bool QWidget::event(QEvent *event)
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
case QEvent::ContextMenu:
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 8c6a234..5f5e1b1 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -60,6 +60,7 @@
#include "QtGui/qregion.h"
#include "QtGui/qsizepolicy.h"
#include "QtGui/qstyle.h"
+#include "QtGui/qevent.h"
#ifdef Q_WS_WIN
#include "QtCore/qt_windows.h"
@@ -664,6 +665,8 @@ public:
}
QSize adjustedSize() const;
+
+ QList<QTouchEvent::TouchPoint *> currentTouchPoints;
};
inline QWExtra *QWidgetPrivate::extraData() const
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index cfdabaf..f53a3ef 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -497,6 +497,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
}
+ // ### don't always register for touch events
+ if (id && QApplicationPrivate::RegisterTouchWindow && !desktop)
+ QApplicationPrivate::RegisterTouchWindow(id, 0);
+
q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
hd = 0; // no display context
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp
index c9161f8..19243aa 100644
--- a/src/network/kernel/qauthenticator.cpp
+++ b/src/network/kernel/qauthenticator.cpp
@@ -52,7 +52,7 @@
QT_BEGIN_NAMESPACE
-#include "../../3rdparty/des/des.cpp"
+#include <../../3rdparty/des/des.cpp>
static QByteArray qNtlmPhase1();
static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phase2data);
diff --git a/tests/auto/qapplication/tst_qapplication.cpp b/tests/auto/qapplication/tst_qapplication.cpp
index cee3125..356768e 100644
--- a/tests/auto/qapplication/tst_qapplication.cpp
+++ b/tests/auto/qapplication/tst_qapplication.cpp
@@ -48,6 +48,7 @@
#include "qabstracteventdispatcher.h"
#include <QtGui>
+#include "private/qapplication_p.h"
#include "private/qstylesheetstyle_p.h"
#ifdef Q_OS_WINCE
#include <windows.h>
@@ -117,6 +118,8 @@ private slots:
void windowsCommandLine_data();
void windowsCommandLine();
+
+ void touchEventPropagation();
};
class MyInputContext : public QInputContext
@@ -1773,6 +1776,146 @@ void tst_QApplication::windowsCommandLine()
#endif
}
+class TouchEventPropagationTestWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ bool seenTouchEvent, acceptTouchEvent, seenMouseEvent, acceptMouseEvent;
+
+ TouchEventPropagationTestWidget(QWidget *parent = 0)
+ : QWidget(parent), seenTouchEvent(false), acceptTouchEvent(false), seenMouseEvent(false), acceptMouseEvent(false)
+ { }
+
+ void reset()
+ {
+ seenTouchEvent = acceptTouchEvent = seenMouseEvent = acceptMouseEvent = false;
+ }
+
+ bool event(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ // qDebug() << objectName() << "seenMouseEvent = true";
+ seenMouseEvent = true;
+ event->setAccepted(acceptMouseEvent);
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ // qDebug() << objectName() << "seenTouchEvent = true";
+ seenTouchEvent = true;
+ event->setAccepted(acceptTouchEvent);
+ break;
+ default:
+ return QWidget::event(event);
+ }
+ return true;
+ }
+};
+
+void tst_QApplication::touchEventPropagation()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QTouchEvent::TouchPoint touchPoint(0);
+ QTouchEvent touchEvent(QEvent::TouchBegin, Qt::NoModifier, QList<QTouchEvent::TouchPoint *>() << (&touchPoint));
+
+ {
+ // touch event behavior on a window
+ TouchEventPropagationTestWidget window;
+ window.setObjectName("1. window");
+
+ QApplicationPrivate::sendTouchEvent(&window, &touchEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(window.seenMouseEvent);
+
+ window.reset();
+ window.setAttribute(Qt::WA_AcceptsTouchEvents);
+ QApplicationPrivate::sendTouchEvent(&window, &touchEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(window.seenMouseEvent);
+
+ window.reset();
+ window.acceptTouchEvent = true;
+ QApplicationPrivate::sendTouchEvent(&window, &touchEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+ }
+
+ {
+ // touch event behavior on a window with a child widget
+ TouchEventPropagationTestWidget window;
+ window.setObjectName("2. window");
+ TouchEventPropagationTestWidget widget(&window);
+ widget.setObjectName("2. widget");
+
+ QApplicationPrivate::sendTouchEvent(&widget, &touchEvent);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.setAttribute(Qt::WA_AcceptsTouchEvents);
+ QApplicationPrivate::sendTouchEvent(&widget, &touchEvent);
+ QVERIFY(widget.seenTouchEvent);
+ QVERIFY(widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.acceptMouseEvent = true;
+ QApplicationPrivate::sendTouchEvent(&widget, &touchEvent);
+ QVERIFY(widget.seenTouchEvent);
+ QVERIFY(widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.acceptTouchEvent = true;
+ QApplicationPrivate::sendTouchEvent(&widget, &touchEvent);
+ QVERIFY(widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.setAttribute(Qt::WA_AcceptsTouchEvents, false);
+ window.setAttribute(Qt::WA_AcceptsTouchEvents);
+ QApplicationPrivate::sendTouchEvent(&widget, &touchEvent);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(widget.seenMouseEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ window.acceptTouchEvent = true;
+ QApplicationPrivate::sendTouchEvent(&widget, &touchEvent);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.acceptMouseEvent = true; // doesn't matter, touch events are propagated first
+ window.acceptTouchEvent = true;
+ QApplicationPrivate::sendTouchEvent(&widget, &touchEvent);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+ }
+}
+
//QTEST_APPLESS_MAIN(tst_QApplication)
int main(int argc, char *argv[])
{
diff --git a/tests/manual/qtouchevent/form.ui b/tests/manual/qtouchevent/form.ui
new file mode 100644
index 0000000..c7fbb78
--- /dev/null
+++ b/tests/manual/qtouchevent/form.ui
@@ -0,0 +1,1897 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>770</width>
+ <height>424</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="testNameLabel">
+ <property name="font">
+ <font>
+ <pointsize>16</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Test Name</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="testDescriptionLabel">
+ <property name="font">
+ <font>
+ <pointsize>16</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Test description</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="TouchWidget" name="greenWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>212</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>85</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>113</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="159">
+ <red>127</red>
+ <green>212</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>212</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>85</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>113</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="159">
+ <red>127</red>
+ <green>212</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>85</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>212</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>85</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>113</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>85</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>85</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <widget class="TouchWidget" name="blueWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>180</width>
+ <height>120</height>
+ </size>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>212</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>85</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>113</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="159">
+ <red>127</red>
+ <green>127</green>
+ <blue>212</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>212</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>85</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>113</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="159">
+ <red>127</red>
+ <green>127</green>
+ <blue>212</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>85</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>212</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>85</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>113</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>85</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>85</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="TouchWidget" name="redWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>212</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>85</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>113</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="159">
+ <red>212</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>212</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>85</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>113</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="159">
+ <red>212</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>85</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>212</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>85</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>113</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>85</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>85</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="1">
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <widget class="TouchWidget" name="greyWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>180</width>
+ <height>120</height>
+ </size>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="159">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="159">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="63">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipBase">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ToolTipText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="autoFillBackground">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>TouchWidget</class>
+ <extends>QWidget</extends>
+ <header>touchwidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp
new file mode 100644
index 0000000..8097ab0
--- /dev/null
+++ b/tests/manual/qtouchevent/main.cpp
@@ -0,0 +1,554 @@
+#include <QtGui>
+#include <QtTest>
+
+#include "ui_form.h"
+#include "touchwidget.h"
+
+class MultitouchTestWidget : public QWidget, public Ui::Form
+{
+ Q_OBJECT
+
+public:
+ MultitouchTestWidget(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ setAttribute(Qt::WA_QuitOnClose, false);
+ setupUi(this);
+ }
+
+ void closeEvent(QCloseEvent *event)
+ {
+ event->accept();
+ QTimer::singleShot(1000, qApp, SLOT(quit()));
+ }
+};
+
+class tst_ManualMultitouch : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_ManualMultitouch();
+ ~tst_ManualMultitouch();
+
+private slots:
+ void ignoringTouchEventsEmulatesMouseEvents();
+ void basicSingleTouchEventHandling();
+ void basicMultiTouchEventHandling();
+ void acceptingTouchBeginStopsPropagation();
+ void ignoringTouchBeginPropagatesToParent();
+ void secondTouchPointOnParentGoesToChild();
+ void secondTouchPointOnChildGoesToParent();
+ void secondTouchPointOnSiblingGoesToSibling();
+ void secondTouchPointOnCousinGoesToCousin();
+};
+
+tst_ManualMultitouch::tst_ManualMultitouch()
+{ }
+
+tst_ManualMultitouch::~tst_ManualMultitouch()
+{ }
+
+void tst_ManualMultitouch::ignoringTouchEventsEmulatesMouseEvents()
+{
+ // first, make sure that we get mouse events when not enabling touch events
+ MultitouchTestWidget testWidget;
+ testWidget.testNameLabel->setText("Mouse Event Emulation Test");
+ testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the green widget.");
+ testWidget.redWidget->hide();
+ testWidget.blueWidget->hide();
+ testWidget.greenWidget->closeWindowOnMouseRelease = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(!testWidget.greenWidget->seenTouchBegin);
+ // QVERIFY(!testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(testWidget.greenWidget->seenMousePress);
+ // QVERIFY(testWidget.greenWidget->seenMouseMove);
+ QVERIFY(testWidget.greenWidget->seenMouseRelease);
+
+ // enable touch, but don't accept the events
+ testWidget.greenWidget->reset();
+ testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.greenWidget->closeWindowOnMouseRelease = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greenWidget->seenTouchBegin);
+ // QVERIFY(!testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(testWidget.greenWidget->seenMousePress);
+ // QVERIFY(testWidget.greenWidget->seenMouseMove);
+ QVERIFY(testWidget.greenWidget->seenMouseRelease);
+}
+
+void tst_ManualMultitouch::basicSingleTouchEventHandling()
+{
+ // now enable touch and make sure we get the touch events
+ MultitouchTestWidget testWidget;
+ testWidget.testNameLabel->setText("Basic Single-Touch Event Handling Test");
+ testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the green widget.");
+ testWidget.redWidget->hide();
+ testWidget.blueWidget->hide();
+ testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.greenWidget->acceptTouchBegin = true;
+ testWidget.greenWidget->acceptTouchUpdate = true;
+ testWidget.greenWidget->acceptTouchEnd = true;
+ testWidget.greenWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greenWidget->seenTouchBegin);
+ // QVERIFY(testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+
+ // again, ignoring the TouchEnd
+ testWidget.greenWidget->reset();
+ testWidget.greenWidget->acceptTouchBegin = true;
+ testWidget.greenWidget->acceptTouchUpdate = true;
+ // testWidget.greenWidget->acceptTouchEnd = true;
+ testWidget.greenWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greenWidget->seenTouchBegin);
+ // QVERIFY(testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+
+ // again, ignoring TouchUpdates
+ testWidget.greenWidget->reset();
+ testWidget.greenWidget->acceptTouchBegin = true;
+ // testWidget.greenWidget->acceptTouchUpdate = true;
+ testWidget.greenWidget->acceptTouchEnd = true;
+ testWidget.greenWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greenWidget->seenTouchBegin);
+ // QVERIFY(testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+
+ // last time, ignoring TouchUpdates and TouchEnd
+ testWidget.greenWidget->reset();
+ testWidget.greenWidget->acceptTouchBegin = true;
+ // testWidget.greenWidget->acceptTouchUpdate = true;
+ // testWidget.greenWidget->acceptTouchEnd = true;
+ testWidget.greenWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greenWidget->seenTouchBegin);
+ // QVERIFY(testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+}
+
+void tst_ManualMultitouch::basicMultiTouchEventHandling()
+{
+ // repeat, this time looking for multiple fingers
+ MultitouchTestWidget testWidget;
+ testWidget.testNameLabel->setText("Basic Multi-Touch Event Handling Test");
+ testWidget.testDescriptionLabel->setText("Touch, hold, and release several fingers on the red widget.");
+ testWidget.greenWidget->hide();
+ testWidget.greyWidget->hide();
+ testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.redWidget->acceptTouchBegin = true;
+ testWidget.redWidget->acceptTouchUpdate = true;
+ testWidget.redWidget->acceptTouchEnd = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(testWidget.redWidget->touchPointCount > 1);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+
+ testWidget.redWidget->reset();
+ testWidget.redWidget->acceptTouchBegin = true;
+ // testWidget.redWidget->acceptTouchUpdate = true;
+ testWidget.redWidget->acceptTouchEnd = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(testWidget.redWidget->touchPointCount > 1);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+
+ testWidget.redWidget->reset();
+ testWidget.redWidget->acceptTouchBegin = true;
+ testWidget.redWidget->acceptTouchUpdate = true;
+ // testWidget.redWidget->acceptTouchEnd = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(testWidget.redWidget->touchPointCount > 1);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+
+ testWidget.redWidget->reset();
+ testWidget.redWidget->acceptTouchBegin = true;
+ // testWidget.redWidget->acceptTouchUpdate = true;
+ // testWidget.redWidget->acceptTouchEnd = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(testWidget.redWidget->touchPointCount > 1);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+}
+
+void tst_ManualMultitouch::acceptingTouchBeginStopsPropagation()
+{
+ // test that accepting the TouchBegin event on the
+ // blueWidget stops propagation to the greenWidget
+ MultitouchTestWidget testWidget;
+ testWidget.testNameLabel->setText("Touch Event Propagation Test: Accepting in Blue Blocks Green");
+ testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the blue widget.");
+ testWidget.redWidget->hide();
+ testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.blueWidget->acceptTouchBegin = true;
+ testWidget.blueWidget->acceptTouchUpdate = true;
+ testWidget.blueWidget->acceptTouchEnd = true;
+ testWidget.blueWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.blueWidget->seenTouchBegin);
+ // QVERIFY(testWidget.blueWidget->seenTouchUpdate);
+ QVERIFY(testWidget.blueWidget->seenTouchEnd);
+ QVERIFY(!testWidget.blueWidget->seenMousePress);
+ QVERIFY(!testWidget.blueWidget->seenMouseMove);
+ QVERIFY(!testWidget.blueWidget->seenMouseRelease);
+ QVERIFY(!testWidget.greenWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+
+ // ignoring TouchEnd
+ testWidget.blueWidget->reset();
+ testWidget.greenWidget->reset();
+ testWidget.blueWidget->acceptTouchBegin = true;
+ testWidget.blueWidget->acceptTouchUpdate = true;
+ // testWidget.blueWidget->acceptTouchEnd = true;
+ testWidget.blueWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.blueWidget->seenTouchBegin);
+ // QVERIFY(testWidget.blueWidget->seenTouchUpdate);
+ QVERIFY(testWidget.blueWidget->seenTouchEnd);
+ QVERIFY(!testWidget.blueWidget->seenMousePress);
+ QVERIFY(!testWidget.blueWidget->seenMouseMove);
+ QVERIFY(!testWidget.blueWidget->seenMouseRelease);
+ QVERIFY(!testWidget.greenWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+
+ // ignoring TouchUpdate
+ testWidget.blueWidget->reset();
+ testWidget.greenWidget->reset();
+ testWidget.blueWidget->acceptTouchBegin = true;
+ // testWidget.blueWidget->acceptTouchUpdate = true;
+ testWidget.blueWidget->acceptTouchEnd = true;
+ testWidget.blueWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.blueWidget->seenTouchBegin);
+ // QVERIFY(testWidget.blueWidget->seenTouchUpdate);
+ QVERIFY(testWidget.blueWidget->seenTouchEnd);
+ QVERIFY(!testWidget.blueWidget->seenMousePress);
+ QVERIFY(!testWidget.blueWidget->seenMouseMove);
+ QVERIFY(!testWidget.blueWidget->seenMouseRelease);
+ QVERIFY(!testWidget.greenWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+
+ // ignoring TouchUpdate and TouchEnd
+ testWidget.blueWidget->reset();
+ testWidget.greenWidget->reset();
+ testWidget.blueWidget->acceptTouchBegin = true;
+ // testWidget.blueWidget->acceptTouchUpdate = true;
+ // testWidget.blueWidget->acceptTouchEnd = true;
+ testWidget.blueWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.blueWidget->seenTouchBegin);
+ // QVERIFY(testWidget.blueWidget->seenTouchUpdate);
+ QVERIFY(testWidget.blueWidget->seenTouchEnd);
+ QVERIFY(!testWidget.blueWidget->seenMousePress);
+ QVERIFY(!testWidget.blueWidget->seenMouseMove);
+ QVERIFY(!testWidget.blueWidget->seenMouseRelease);
+ QVERIFY(!testWidget.greenWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+}
+
+void tst_ManualMultitouch::ignoringTouchBeginPropagatesToParent()
+{
+ // repeat the test above, now ignoring touch events in the
+ // greyWidget, they should be propagated to the redWidget
+ MultitouchTestWidget testWidget;
+ testWidget.testNameLabel->setText("Touch Event Propagation Test: Ignoring in Grey Propagates to Red");
+ testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the grey widget.");
+ testWidget.greenWidget->hide();
+ testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents, false);
+ testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.greyWidget->reset();
+ testWidget.redWidget->reset();
+ testWidget.redWidget->acceptTouchBegin = true;
+ testWidget.redWidget->acceptTouchUpdate = true;
+ testWidget.redWidget->acceptTouchEnd = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(!testWidget.greyWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greyWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greyWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greyWidget->seenMousePress);
+ QVERIFY(!testWidget.greyWidget->seenMouseMove);
+ QVERIFY(!testWidget.greyWidget->seenMouseRelease);
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ // QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(!testWidget.redWidget->seenMousePress);
+ QVERIFY(!testWidget.redWidget->seenMouseMove);
+ QVERIFY(!testWidget.redWidget->seenMouseRelease);
+
+ // again, but this time greyWidget should see the TouchBegin
+ testWidget.greyWidget->reset();
+ testWidget.redWidget->reset();
+ testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.redWidget->acceptTouchBegin = true;
+ testWidget.redWidget->acceptTouchUpdate = true;
+ testWidget.redWidget->acceptTouchEnd = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greyWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greyWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greyWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greyWidget->seenMousePress);
+ QVERIFY(!testWidget.greyWidget->seenMouseMove);
+ QVERIFY(!testWidget.greyWidget->seenMouseRelease);
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ // QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(!testWidget.redWidget->seenMousePress);
+ QVERIFY(!testWidget.redWidget->seenMouseMove);
+ QVERIFY(!testWidget.redWidget->seenMouseRelease);
+
+ // again, ignoring the TouchEnd
+ testWidget.greyWidget->reset();
+ testWidget.redWidget->reset();
+ testWidget.redWidget->acceptTouchBegin = true;
+ testWidget.redWidget->acceptTouchUpdate = true;
+ // testWidget.redWidget->acceptTouchEnd = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greyWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greyWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greyWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greyWidget->seenMousePress);
+ QVERIFY(!testWidget.greyWidget->seenMouseMove);
+ QVERIFY(!testWidget.greyWidget->seenMouseRelease);
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ // QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(!testWidget.redWidget->seenMousePress);
+ QVERIFY(!testWidget.redWidget->seenMouseMove);
+ QVERIFY(!testWidget.redWidget->seenMouseRelease);
+
+ // again, ignoring TouchUpdates
+ testWidget.greyWidget->reset();
+ testWidget.redWidget->reset();
+ testWidget.redWidget->acceptTouchBegin = true;
+ // testWidget.redWidget->acceptTouchUpdate = true;
+ testWidget.redWidget->acceptTouchEnd = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greyWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greyWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greyWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greyWidget->seenMousePress);
+ QVERIFY(!testWidget.greyWidget->seenMouseMove);
+ QVERIFY(!testWidget.greyWidget->seenMouseRelease);
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ // QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(!testWidget.redWidget->seenMousePress);
+ QVERIFY(!testWidget.redWidget->seenMouseMove);
+ QVERIFY(!testWidget.redWidget->seenMouseRelease);
+
+ // last time, ignoring TouchUpdates and TouchEnd
+ testWidget.greyWidget->reset();
+ testWidget.redWidget->reset();
+ testWidget.redWidget->acceptTouchBegin = true;
+ // testWidget.redWidget->acceptTouchUpdate = true;
+ // testWidget.redWidget->acceptTouchEnd = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greyWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greyWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greyWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greyWidget->seenMousePress);
+ QVERIFY(!testWidget.greyWidget->seenMouseMove);
+ QVERIFY(!testWidget.blueWidget->seenMouseRelease);
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ // QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(!testWidget.redWidget->seenMousePress);
+ QVERIFY(!testWidget.redWidget->seenMouseMove);
+ QVERIFY(!testWidget.redWidget->seenMouseRelease);
+}
+
+void tst_ManualMultitouch::secondTouchPointOnParentGoesToChild()
+{
+ MultitouchTestWidget testWidget;
+ testWidget.testNameLabel->setText("Additional Touch-Points Outside Child's Rect Go to Child");
+ testWidget.testDescriptionLabel->setText("Press and hold a finger on the blue widget, then on the green one, and release.");
+ testWidget.redWidget->hide();
+ testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.blueWidget->acceptTouchBegin = true;
+ testWidget.greenWidget->acceptTouchBegin = true;
+ testWidget.blueWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.blueWidget->seenTouchBegin);
+ // QVERIFY(testWidget.blueWidget->seenTouchUpdate);
+ QVERIFY(testWidget.blueWidget->seenTouchEnd);
+ QVERIFY(!testWidget.blueWidget->seenMousePress);
+ QVERIFY(!testWidget.blueWidget->seenMouseMove);
+ QVERIFY(!testWidget.blueWidget->seenMouseRelease);
+ QVERIFY(testWidget.blueWidget->touchPointCount > 1);
+ QVERIFY(!testWidget.greenWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+}
+
+void tst_ManualMultitouch::secondTouchPointOnChildGoesToParent()
+{
+ MultitouchTestWidget testWidget;
+ testWidget.testNameLabel->setText("Additional Touch-Points Over Child's Rect Go to Parent");
+ testWidget.testDescriptionLabel->setText("Press and hold a finger on the red widget, then on the grey one, and release.");
+ testWidget.greenWidget->hide();
+ testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.greyWidget->acceptTouchBegin = true;
+ testWidget.redWidget->acceptTouchBegin = true;
+ testWidget.redWidget->closeWindowOnTouchEnd = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ // QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(!testWidget.redWidget->seenMousePress);
+ QVERIFY(!testWidget.redWidget->seenMouseMove);
+ QVERIFY(!testWidget.redWidget->seenMouseRelease);
+ QVERIFY(testWidget.redWidget->touchPointCount > 1);
+ QVERIFY(!testWidget.greyWidget->seenTouchBegin);
+ QVERIFY(!testWidget.greyWidget->seenTouchUpdate);
+ QVERIFY(!testWidget.greyWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greyWidget->seenMousePress);
+ QVERIFY(!testWidget.greyWidget->seenMouseMove);
+ QVERIFY(!testWidget.greyWidget->seenMouseRelease);
+}
+
+void tst_ManualMultitouch::secondTouchPointOnSiblingGoesToSibling()
+{
+ MultitouchTestWidget testWidget;
+ testWidget.testNameLabel->setText("Multi-Touch Interaction Test, Unrelated Widgets Get Separate Events");
+ testWidget.testDescriptionLabel->setText("Press and hold a finger on the green widget, then the red one, and release.");
+ testWidget.blueWidget->hide();
+ testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.greenWidget->acceptTouchBegin = true;
+ testWidget.greenWidget->closeWindowOnTouchEnd = true;
+ testWidget.greyWidget->hide();
+ testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.redWidget->acceptTouchBegin = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.greenWidget->seenTouchBegin);
+ // QVERIFY(testWidget.greenWidget->seenTouchUpdate);
+ QVERIFY(testWidget.greenWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greenWidget->seenMousePress);
+ QVERIFY(!testWidget.greenWidget->seenMouseMove);
+ QVERIFY(!testWidget.greenWidget->seenMouseRelease);
+ QVERIFY(testWidget.redWidget->seenTouchBegin);
+ // QVERIFY(testWidget.redWidget->seenTouchUpdate);
+ QVERIFY(testWidget.redWidget->seenTouchEnd);
+ QVERIFY(!testWidget.redWidget->seenMousePress);
+ QVERIFY(!testWidget.redWidget->seenMouseMove);
+ QVERIFY(!testWidget.redWidget->seenMouseRelease);
+ QVERIFY(testWidget.greenWidget->touchPointCount == 1);
+ QVERIFY(testWidget.redWidget->touchPointCount == 1);
+}
+
+void tst_ManualMultitouch::secondTouchPointOnCousinGoesToCousin()
+{
+ MultitouchTestWidget testWidget;
+ testWidget.testNameLabel->setText("Multi-Touch Interaction Test, Unrelated Widgets Get Separate Events");
+ testWidget.testDescriptionLabel->setText("Press and hold a finger on the blue widget, then the grey one, and release.");
+ testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.blueWidget->acceptTouchBegin = true;
+ testWidget.blueWidget->closeWindowOnTouchEnd = true;
+ testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents);
+ testWidget.greyWidget->acceptTouchBegin = true;
+ testWidget.showMaximized();
+ (void) qApp->exec();
+ QVERIFY(testWidget.blueWidget->seenTouchBegin);
+ // QVERIFY(testWidget.blueWidget->seenTouchUpdate);
+ QVERIFY(testWidget.blueWidget->seenTouchEnd);
+ QVERIFY(!testWidget.blueWidget->seenMousePress);
+ QVERIFY(!testWidget.blueWidget->seenMouseMove);
+ QVERIFY(!testWidget.blueWidget->seenMouseRelease);
+ QVERIFY(testWidget.greyWidget->seenTouchBegin);
+ // QVERIFY(testWidget.greyWidget->seenTouchUpdate);
+ QVERIFY(testWidget.greyWidget->seenTouchEnd);
+ QVERIFY(!testWidget.greyWidget->seenMousePress);
+ QVERIFY(!testWidget.greyWidget->seenMouseMove);
+ QVERIFY(!testWidget.greyWidget->seenMouseRelease);
+ QVERIFY(testWidget.blueWidget->touchPointCount == 1);
+ QVERIFY(testWidget.greyWidget->touchPointCount == 1);
+}
+
+QTEST_MAIN(tst_ManualMultitouch)
+
+#include "main.moc"
diff --git a/tests/manual/qtouchevent/multitouch.pro b/tests/manual/qtouchevent/multitouch.pro
new file mode 100644
index 0000000..de1ee06
--- /dev/null
+++ b/tests/manual/qtouchevent/multitouch.pro
@@ -0,0 +1,5 @@
+QT += testlib
+SOURCES = main.cpp \
+ touchwidget.cpp
+FORMS += form.ui
+HEADERS += touchwidget.h
diff --git a/tests/manual/qtouchevent/touchwidget.cpp b/tests/manual/qtouchevent/touchwidget.cpp
new file mode 100644
index 0000000..a8141cc
--- /dev/null
+++ b/tests/manual/qtouchevent/touchwidget.cpp
@@ -0,0 +1,94 @@
+#include "touchwidget.h"
+
+#include <QApplication>
+#include <QtEvents>
+#include <QTimer>
+#include <QTouchEvent>
+
+void TouchWidget::reset()
+{
+ acceptTouchBegin
+ = acceptTouchUpdate
+ = acceptTouchEnd
+ = seenTouchBegin
+ = seenTouchUpdate
+ = seenTouchEnd
+ = closeWindowOnTouchEnd
+
+ = acceptMousePress
+ = acceptMouseMove
+ = acceptMouseRelease
+ = seenMousePress
+ = seenMouseMove
+ = seenMouseRelease
+ = closeWindowOnMouseRelease
+
+ = false;
+ touchPointCount = 0;
+}
+
+bool TouchWidget::event(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (seenTouchBegin) qWarning("TouchBegin: already seen a TouchBegin");
+ if (seenTouchUpdate) qWarning("TouchBegin: TouchUpdate cannot happen before TouchBegin");
+ if (seenTouchEnd) qWarning("TouchBegin: TouchEnd cannot happen before TouchBegin");
+ seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd;
+ touchPointCount = qMax(touchPointCount, static_cast<QTouchEvent *>(event)->touchPoints().count());
+ if (acceptTouchBegin) {
+ event->accept();
+ return true;
+ }
+ break;
+ case QEvent::TouchUpdate:
+ if (!seenTouchBegin) qWarning("TouchUpdate: have not seen TouchBegin");
+ if (seenTouchEnd) qWarning("TouchUpdate: TouchEnd cannot happen before TouchUpdate");
+ seenTouchUpdate = seenTouchBegin && !seenTouchEnd;
+ touchPointCount = qMax(touchPointCount, static_cast<QTouchEvent *>(event)->touchPoints().count());
+ if (acceptTouchUpdate) {
+ event->accept();
+ return true;
+ }
+ break;
+ case QEvent::TouchEnd:
+ if (!seenTouchBegin) qWarning("TouchEnd: have not seen TouchBegin");
+ if (seenTouchEnd) qWarning("TouchEnd: already seen a TouchEnd");
+ seenTouchEnd = seenTouchBegin && !seenTouchEnd;
+ touchPointCount = qMax(touchPointCount, static_cast<QTouchEvent *>(event)->touchPoints().count());
+ if (closeWindowOnTouchEnd)
+ window()->close();
+ if (acceptTouchEnd) {
+ event->accept();
+ return true;
+ }
+ break;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ seenMousePress = true;
+ if (acceptMousePress) {
+ event->accept();
+ return true;
+ }
+ break;
+ case QEvent::MouseMove:
+ seenMouseMove = true;
+ if (acceptMouseMove) {
+ event->accept();
+ return true;
+ }
+ break;
+ case QEvent::MouseButtonRelease:
+ seenMouseRelease = true;
+ if (closeWindowOnMouseRelease)
+ window()->close();
+ if (acceptMouseRelease) {
+ event->accept();
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(event);
+}
diff --git a/tests/manual/qtouchevent/touchwidget.h b/tests/manual/qtouchevent/touchwidget.h
new file mode 100644
index 0000000..2726deb
--- /dev/null
+++ b/tests/manual/qtouchevent/touchwidget.h
@@ -0,0 +1,31 @@
+#ifndef TOUCHWIDGET_H
+#define TOUCHWIDGET_H
+
+#include <QWidget>
+
+class TouchWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd;
+ bool seenTouchBegin, seenTouchUpdate, seenTouchEnd;
+ bool closeWindowOnTouchEnd;
+ int touchPointCount;
+
+ bool acceptMousePress, acceptMouseMove, acceptMouseRelease;
+ bool seenMousePress, seenMouseMove, seenMouseRelease;
+ bool closeWindowOnMouseRelease;
+
+ inline TouchWidget(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ reset();
+ }
+
+ void reset();
+
+ bool event(QEvent *event);
+};
+
+#endif // TOUCHWIDGET_H