1/*
2 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this program; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#include "config.h"
22#include "qwebkittest_p.h"
23
24#include "PageViewportControllerClientQt.h"
25#include "qquickwebview_p_p.h"
26#include <QMutableListIterator>
27#include <QTouchEvent>
28#include <QWheelEvent>
29#include <qpa/qwindowsysteminterface.h>
30
31using namespace WebKit;
32
33QWebKitTest::QWebKitTest(QQuickWebViewPrivate* webViewPrivate, QObject* parent)
34    : QObject(parent)
35    , m_webViewPrivate(webViewPrivate)
36{
37}
38
39QWebKitTest::~QWebKitTest()
40{
41}
42
43static QTouchEvent::TouchPoint touchPoint(qreal x, qreal y)
44{
45    QPointF localPos(x, y);
46
47    QTouchEvent::TouchPoint point;
48    point.setId(1);
49    point.setLastPos(localPos);
50    QRectF touchRect(0, 0, 40, 40);
51    touchRect.moveCenter(localPos);
52    point.setRect(touchRect);
53    point.setPressure(1);
54
55    return point;
56}
57
58bool QWebKitTest::sendTouchEvent(QQuickWebView* window, QEvent::Type type, const QList<QTouchEvent::TouchPoint>& points, ulong timestamp)
59{
60    ASSERT(window);
61
62    static QTouchDevice* device = 0;
63    if (!device) {
64        device = new QTouchDevice;
65        device->setType(QTouchDevice::TouchScreen);
66        QWindowSystemInterface::registerTouchDevice(device);
67    }
68
69    Qt::TouchPointStates touchPointStates = 0;
70    foreach (const QTouchEvent::TouchPoint& touchPoint, points)
71        touchPointStates |= touchPoint.state();
72
73    QTouchEvent event(type, device, Qt::NoModifier, touchPointStates, points);
74    event.setTimestamp(timestamp);
75    event.setAccepted(false);
76
77    window->touchEvent(&event);
78
79    return event.isAccepted();
80}
81
82bool QWebKitTest::touchTap(QObject* item, qreal x, qreal y, int delay)
83{
84    QQuickWebView* window = qobject_cast<QQuickWebView*>(item);
85
86    if (!window) {
87        qWarning("Touch event \"TouchBegin\" not accepted by receiving item");
88        return false;
89    }
90
91    // FIXME: implement delay using QTest::qWait() or similar.
92    Q_UNUSED(delay);
93
94    QList<QTouchEvent::TouchPoint> points;
95    points.append(touchPoint(x, y));
96
97    points[0].setState(Qt::TouchPointPressed);
98    sendTouchEvent(window, QEvent::TouchBegin, points, QDateTime::currentMSecsSinceEpoch());
99
100    points[0].setState(Qt::TouchPointReleased);
101    sendTouchEvent(window, QEvent::TouchEnd, points, QDateTime::currentMSecsSinceEpoch());
102
103    return true;
104}
105
106bool QWebKitTest::touchDoubleTap(QObject* item, qreal x, qreal y, int delay)
107{
108    if (!touchTap(item, x, y, delay))
109        return false;
110
111    if (!touchTap(item, x, y, delay))
112        return false;
113
114    return true;
115}
116
117bool QWebKitTest::wheelEvent(QObject* item, qreal x, qreal y, int delta, Qt::Orientation orient)
118{
119    QQuickWebView* window = qobject_cast<QQuickWebView*>(item);
120
121    if (!window) {
122        qWarning("Wheel event not accepted by receiving item");
123        return false;
124    }
125
126    QWheelEvent event(QPointF(x, y), delta, Qt::NoButton, Qt::NoModifier, orient);
127    event.setTimestamp(QDateTime::currentMSecsSinceEpoch());
128    event.setAccepted(false);
129
130    window->wheelEvent(&event);
131
132    return event.isAccepted();
133}
134
135QSize QWebKitTest::contentsSize() const
136{
137    return QSize(m_webViewPrivate->pageView->contentsSize().toSize());
138}
139
140static inline QJsonObject toJsonObject(const QSizeF& sizeF)
141{
142    QJsonObject result;
143    result.insert(QLatin1String("width"), sizeF.width());
144    result.insert(QLatin1String("height"), sizeF.height());
145    return result;
146}
147
148QJsonObject QWebKitTest::viewport() const
149{
150    QJsonObject viewportData;
151    if (const PageViewportController* const viewportHandler = m_webViewPrivate->viewportController()) {
152        viewportData.insert(QLatin1String("layoutSize"), toJsonObject(viewportHandler->contentsLayoutSize()));
153        viewportData.insert(QLatin1String("isScalable"), viewportHandler->allowsUserScaling());
154        viewportData.insert(QLatin1String("minimumScale"), viewportHandler->minimumScale());
155        viewportData.insert(QLatin1String("maximumScale"), viewportHandler->maximumScale());
156    } else {
157        viewportData.insert(QLatin1String("initialScale"), 1.0);
158        viewportData.insert(QLatin1String("layoutSize"), toJsonObject(QSizeF()));
159        viewportData.insert(QLatin1String("isScalable"), false);
160        viewportData.insert(QLatin1String("minimumScale"), 1.0);
161        viewportData.insert(QLatin1String("maximumScale"), 1.0);
162    }
163    return viewportData;
164}
165
166QVariant QWebKitTest::devicePixelRatio() const
167{
168    if (const PageViewportController* const viewport = m_webViewPrivate->viewportController())
169        return viewport->deviceScaleFactor();
170    return 1.0;
171}
172
173QVariant QWebKitTest::contentsScale() const
174{
175    if (const PageViewportController* const viewport = m_webViewPrivate->viewportController())
176        return viewport->currentScale();
177    return 1.0;
178}
179