1/*
2 * Copyright (C) 2010, 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 "qquickwebpage_p.h"
23
24#include "QtWebPageEventHandler.h"
25#include "QtWebPageSGNode.h"
26#include "TransformationMatrix.h"
27#include "qquickwebpage_p_p.h"
28#include "qquickwebview_p.h"
29#include "qquickwebview_p_p.h"
30#include "qwebkittest_p.h"
31#include <QQuickWindow>
32#include <WKPage.h>
33#include <WebCore/CoordinatedGraphicsScene.h>
34
35using namespace WebKit;
36
37QQuickWebPage::QQuickWebPage(QQuickWebView* viewportItem)
38    : QQuickItem(viewportItem->contentItem())
39    , d(new QQuickWebPagePrivate(this, viewportItem))
40{
41    setFlag(ItemHasContents);
42    setClip(true);
43
44    // We do the transform from the top left so the viewport can assume the position 0, 0
45    // is always where rendering starts.
46    setTransformOrigin(TopLeft);
47}
48
49QQuickWebPage::~QQuickWebPage()
50{
51    delete d;
52}
53
54QQuickWebPagePrivate::QQuickWebPagePrivate(QQuickWebPage* q, QQuickWebView* viewportItem)
55    : q(q)
56    , viewportItem(viewportItem)
57    , paintingIsInitialized(false)
58    , contentsScale(1)
59{
60}
61
62void QQuickWebPagePrivate::paint(QPainter* painter)
63{
64    if (WebCore::CoordinatedGraphicsScene* scene = QQuickWebViewPrivate::get(viewportItem)->coordinatedGraphicsScene())
65        scene->paintToGraphicsContext(painter);
66}
67
68
69QSGNode* QQuickWebPage::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*)
70{
71    QQuickWebViewPrivate* webViewPrivate = QQuickWebViewPrivate::get(d->viewportItem);
72
73    WebCore::CoordinatedGraphicsScene* scene = webViewPrivate->coordinatedGraphicsScene();
74    if (!scene)
75        return oldNode;
76
77    QtWebPageSGNode* node = static_cast<QtWebPageSGNode*>(oldNode);
78
79    const QWindow* window = this->window();
80    ASSERT(window);
81
82    WKPageRef pageRef = webViewPrivate->webPage.get();
83    if (window && WKPageGetBackingScaleFactor(pageRef) != window->devicePixelRatio()) {
84        WKPageSetCustomBackingScaleFactor(pageRef, window->devicePixelRatio());
85        // This signal is queued since if we are running a threaded renderer. This might cause failures
86        // if tests are reading the new value between the property change and the signal emission.
87        emit d->viewportItem->experimental()->test()->devicePixelRatioChanged();
88    }
89
90    if (!node)
91        node = new QtWebPageSGNode;
92
93    node->setCoordinatedGraphicsScene(scene);
94
95    node->setScale(d->contentsScale);
96    node->setDevicePixelRatio(window->devicePixelRatio());
97    QColor backgroundColor = webViewPrivate->transparentBackground() ? Qt::transparent : Qt::white;
98    QRectF backgroundRect(QPointF(0, 0), d->contentsSize);
99    node->setBackground(backgroundRect, backgroundColor);
100
101    return node;
102}
103
104void QQuickWebPage::setContentsSize(const QSizeF& size)
105{
106    if (size.isEmpty() || d->contentsSize == size)
107        return;
108
109    d->contentsSize = size;
110    d->updateSize();
111    emit d->viewportItem->experimental()->test()->contentsSizeChanged();
112}
113
114const QSizeF& QQuickWebPage::contentsSize() const
115{
116    return d->contentsSize;
117}
118
119void QQuickWebPage::setContentsScale(qreal scale)
120{
121    ASSERT(scale > 0);
122    d->contentsScale = scale;
123    d->updateSize();
124    emit d->viewportItem->experimental()->test()->contentsScaleChanged();
125}
126
127qreal QQuickWebPage::contentsScale() const
128{
129    ASSERT(d->contentsScale > 0);
130    return d->contentsScale;
131}
132
133QTransform QQuickWebPage::transformFromItem() const
134{
135    return transformToItem().inverted();
136}
137
138QTransform QQuickWebPage::transformToItem() const
139{
140    qreal xPos = x();
141    qreal yPos = y();
142
143    if (d->viewportItem->experimental()->flickableViewportEnabled()) {
144        // Flickable moves its contentItem so we need to take that position into
145        // account, as well as the potential displacement of the page on the
146        // contentItem because of additional QML items.
147        xPos += d->viewportItem->contentItem()->x();
148        yPos += d->viewportItem->contentItem()->y();
149    }
150
151    return QTransform(d->contentsScale, 0, 0, 0, d->contentsScale, 0, xPos, yPos, 1);
152}
153
154void QQuickWebPagePrivate::updateSize()
155{
156    QSizeF scaledSize = contentsSize * contentsScale;
157
158    q->setSize(scaledSize);
159
160    if (viewportItem->experimental()->flickableViewportEnabled()) {
161        // Make sure that the content is sized to the page if the user did not
162        // add other flickable items. If that is not the case, the user needs to
163        // disable the default content item size property on the WebView and
164        // bind the contentWidth and contentHeight accordingly, in accordance
165        // accordance with normal Flickable behaviour.
166        if (viewportItem->experimental()->useDefaultContentItemSize()) {
167            viewportItem->setContentWidth(scaledSize.width());
168            viewportItem->setContentHeight(scaledSize.height());
169        }
170    }
171}
172
173QQuickWebPagePrivate::~QQuickWebPagePrivate()
174{
175}
176
177#include "moc_qquickwebpage_p.cpp"
178