~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies)
 
3
 * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org>
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Library General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Library General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Library General Public License
 
16
 * along with this program; see the file COPYING.LIB.  If not, write to
 
17
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
18
 * Boston, MA 02110-1301, USA.
 
19
 *
 
20
 */
 
21
 
 
22
 
 
23
#include "config.h"
 
24
#include "PageViewportControllerClientQt.h"
 
25
 
 
26
#include "qquickwebpage_p.h"
 
27
#include "qquickwebview_p.h"
 
28
#include "qwebkittest_p.h"
 
29
#include <QPointF>
 
30
#include <QTransform>
 
31
#include <QtQuick/qquickitem.h>
 
32
#include <WebCore/FloatRect.h>
 
33
#include <WebCore/FloatSize.h>
 
34
 
 
35
using namespace WebCore;
 
36
 
 
37
namespace WebKit {
 
38
 
 
39
static const int kScaleAnimationDurationMillis = 250;
 
40
 
 
41
PageViewportControllerClientQt::PageViewportControllerClientQt(QQuickWebView* viewportItem, QQuickWebPage* pageItem)
 
42
    : m_viewportItem(viewportItem)
 
43
    , m_pageItem(pageItem)
 
44
    , m_scaleAnimation(new ScaleAnimation(this))
 
45
    , m_pinchStartScale(-1)
 
46
    , m_lastCommittedScale(-1)
 
47
    , m_zoomOutScale(0)
 
48
    , m_isUserInteracting(false)
 
49
    , m_ignoreViewportChanges(true)
 
50
{
 
51
    m_scaleAnimation->setDuration(kScaleAnimationDurationMillis);
 
52
    m_scaleAnimation->setEasingCurve(QEasingCurve::OutCubic);
 
53
 
 
54
    connect(m_viewportItem, SIGNAL(movementStarted()), SLOT(flickMoveStarted()), Qt::DirectConnection);
 
55
    connect(m_viewportItem, SIGNAL(movementEnded()), SLOT(flickMoveEnded()), Qt::DirectConnection);
 
56
    connect(m_viewportItem, SIGNAL(contentXChanged()), SLOT(pageItemPositionChanged()));
 
57
    connect(m_viewportItem, SIGNAL(contentYChanged()), SLOT(pageItemPositionChanged()));
 
58
 
 
59
 
 
60
    connect(m_scaleAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)),
 
61
            SLOT(scaleAnimationStateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
 
62
}
 
63
 
 
64
void PageViewportControllerClientQt::ScaleAnimation::updateCurrentValue(const QVariant& value)
 
65
{
 
66
    // Resetting the end value, the easing curve or the duration of the scale animation
 
67
    // triggers a recalculation of the animation interval. This might change the current
 
68
    // value of the animated property.
 
69
    // Make sure we only act on animation value changes if the animation is active.
 
70
    if (!m_controllerClient->scaleAnimationActive())
 
71
        return;
 
72
 
 
73
    QRectF itemRect = value.toRectF();
 
74
    float itemScale = m_controllerClient->viewportScaleForRect(itemRect);
 
75
 
 
76
    m_controllerClient->setContentRectVisiblePositionAtScale(itemRect.topLeft(), itemScale);
 
77
}
 
78
 
 
79
PageViewportControllerClientQt::~PageViewportControllerClientQt()
 
80
{
 
81
}
 
82
 
 
83
void PageViewportControllerClientQt::setContentRectVisiblePositionAtScale(const QPointF& location, qreal itemScale)
 
84
{
 
85
    ASSERT(itemScale >= 0);
 
86
 
 
87
    scaleContent(itemScale);
 
88
 
 
89
    // To animate the position together with the scale we multiply the position with the current scale
 
90
    // and add it to the page position (displacement on the flickable contentItem because of additional items).
 
91
    QPointF newPosition(m_pageItem->pos() + location * itemScale);
 
92
 
 
93
    m_viewportItem->setContentPos(newPosition);
 
94
}
 
95
 
 
96
void PageViewportControllerClientQt::animateContentRectVisible(const QRectF& contentRect)
 
97
{
 
98
    ASSERT(m_scaleAnimation->state() == QAbstractAnimation::Stopped);
 
99
 
 
100
    ASSERT(!scrollAnimationActive());
 
101
    if (scrollAnimationActive())
 
102
        return;
 
103
 
 
104
    QRectF viewportRectInContentCoords = m_viewportItem->mapRectToWebContent(m_viewportItem->boundingRect());
 
105
    if (contentRect == viewportRectInContentCoords) {
 
106
        m_controller->resumeContent();
 
107
        return;
 
108
    }
 
109
 
 
110
    // Inform the web process about the requested visible content rect immediately so that new tiles
 
111
    // are rendered at the final destination during the animation.
 
112
    m_controller->didChangeContentsVisibility(contentRect.topLeft(), viewportScaleForRect(contentRect));
 
113
 
 
114
    // Since we have to animate scale and position at the same time the scale animation interpolates
 
115
    // from the current viewport rect in content coordinates to a visible rect of the content.
 
116
    m_scaleAnimation->setStartValue(viewportRectInContentCoords);
 
117
    m_scaleAnimation->setEndValue(contentRect);
 
118
 
 
119
    m_scaleAnimation->start();
 
120
}
 
121
 
 
122
void PageViewportControllerClientQt::flickMoveStarted()
 
123
{
 
124
    m_controller->suspendContent();
 
125
 
 
126
    m_lastScrollPosition = m_viewportItem->contentPos();
 
127
 
 
128
    m_ignoreViewportChanges = false;
 
129
}
 
130
 
 
131
void PageViewportControllerClientQt::flickMoveEnded()
 
132
{
 
133
    // This method is called on the end of the pan or pan kinetic animation.
 
134
 
 
135
    m_ignoreViewportChanges = true;
 
136
    if (!m_isUserInteracting)
 
137
        m_controller->resumeContent();
 
138
}
 
139
 
 
140
void PageViewportControllerClientQt::pageItemPositionChanged()
 
141
{
 
142
    if (m_ignoreViewportChanges)
 
143
        return;
 
144
 
 
145
    QPointF newPosition = m_viewportItem->contentPos();
 
146
 
 
147
    updateViewportController(m_lastScrollPosition - newPosition);
 
148
 
 
149
    m_lastScrollPosition = newPosition;
 
150
}
 
151
 
 
152
void PageViewportControllerClientQt::scaleAnimationStateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State /*oldState*/)
 
153
{
 
154
    switch (newState) {
 
155
    case QAbstractAnimation::Running:
 
156
        m_viewportItem->cancelFlick();
 
157
        m_controller->suspendContent();
 
158
        break;
 
159
    case QAbstractAnimation::Stopped:
 
160
        m_controller->resumeContent();
 
161
        break;
 
162
    default:
 
163
        break;
 
164
    }
 
165
}
 
166
 
 
167
void PageViewportControllerClientQt::touchBegin()
 
168
{
 
169
    m_controller->setHadUserInteraction(true);
 
170
 
 
171
    // Prevents resuming the page between the user's flicks of the page.
 
172
    m_isUserInteracting = true;
 
173
}
 
174
 
 
175
void PageViewportControllerClientQt::touchEnd()
 
176
{
 
177
    m_isUserInteracting = false;
 
178
}
 
179
 
 
180
void PageViewportControllerClientQt::focusEditableArea(const QRectF& caretArea, const QRectF& targetArea)
 
181
{
 
182
    // This can only happen as a result of a user interaction.
 
183
    ASSERT(m_controller->hadUserInteraction());
 
184
 
 
185
    const float editingFixedScale = 2 * m_controller->devicePixelRatio();
 
186
    float targetScale = m_controller->innerBoundedViewportScale(editingFixedScale);
 
187
    const QRectF viewportRect = m_viewportItem->boundingRect();
 
188
 
 
189
    qreal x;
 
190
    const qreal borderOffset = 10 * m_controller->devicePixelRatio();
 
191
    if ((targetArea.width() + borderOffset) * targetScale <= viewportRect.width()) {
 
192
        // Center the input field in the middle of the view, if it is smaller than
 
193
        // the view at the scale target.
 
194
        x = viewportRect.center().x() - targetArea.width() * targetScale / 2.0;
 
195
    } else {
 
196
        // Ensure that the caret always has borderOffset contents pixels to the right
 
197
        // of it, and secondarily (if possible), that the area has borderOffset
 
198
        // contents pixels to the left of it.
 
199
        qreal caretOffset = caretArea.x() - targetArea.x();
 
200
        x = qMin(viewportRect.width() - (caretOffset + borderOffset) * targetScale, borderOffset * targetScale);
 
201
    }
 
202
 
 
203
    const QPointF hotspot = QPointF(targetArea.x(), targetArea.center().y());
 
204
    const QPointF viewportHotspot = QPointF(x, /* FIXME: visibleCenter */ viewportRect.center().y());
 
205
 
 
206
    QPointF endPosition = hotspot - viewportHotspot / targetScale;
 
207
    endPosition = m_controller->clampViewportToContents(endPosition, targetScale);
 
208
    QRectF endVisibleContentRect(endPosition, viewportRect.size() / targetScale);
 
209
 
 
210
    animateContentRectVisible(endVisibleContentRect);
 
211
}
 
212
 
 
213
void PageViewportControllerClientQt::zoomToAreaGestureEnded(const QPointF& touchPoint, const QRectF& targetArea)
 
214
{
 
215
    // This can only happen as a result of a user interaction.
 
216
    ASSERT(m_controller->hadUserInteraction());
 
217
 
 
218
    if (!targetArea.isValid())
 
219
        return;
 
220
 
 
221
    if (m_controller->hasSuspendedContent())
 
222
        return;
 
223
 
 
224
    const float margin = 10 * m_controller->devicePixelRatio(); // We want at least a little bit of margin.
 
225
    QRectF endArea = targetArea.adjusted(-margin, -margin, margin, margin);
 
226
 
 
227
    const QRectF viewportRect = m_viewportItem->boundingRect();
 
228
 
 
229
    qreal minViewportScale = qreal(2.5) * m_controller->devicePixelRatio();
 
230
    qreal targetScale = viewportRect.size().width() / endArea.size().width();
 
231
    targetScale = m_controller->innerBoundedViewportScale(qMin(minViewportScale, targetScale));
 
232
    qreal currentScale = m_pageItem->contentsScale();
 
233
 
 
234
    // We want to end up with the target area filling the whole width of the viewport (if possible),
 
235
    // and centralized vertically where the user requested zoom. Thus our hotspot is the center of
 
236
    // the targetArea x-wise and the requested zoom position, y-wise.
 
237
    const QPointF hotspot = QPointF(endArea.center().x(), touchPoint.y());
 
238
    const QPointF viewportHotspot = viewportRect.center();
 
239
 
 
240
    QPointF endPosition = hotspot - viewportHotspot / targetScale;
 
241
    endPosition = m_controller->clampViewportToContents(endPosition, targetScale);
 
242
    QRectF endVisibleContentRect(endPosition, viewportRect.size() / targetScale);
 
243
 
 
244
    enum { ZoomIn, ZoomBack, ZoomOut, NoZoom } zoomAction = ZoomIn;
 
245
 
 
246
    // Zoom back out if attempting to scale to the same current scale, or
 
247
    // attempting to continue scaling out from the inner most level.
 
248
    // Use fuzzy compare with a fixed error to be able to deal with largish differences due to pixel rounding.
 
249
    if (!m_scaleStack.isEmpty() && fuzzyCompare(targetScale, currentScale, 0.01)) {
 
250
        // If moving the viewport would expose more of the targetRect and move at least 40 pixels, update position but do not scale out.
 
251
        QRectF currentContentRect(m_viewportItem->mapRectToWebContent(viewportRect));
 
252
        QRectF targetIntersection = endVisibleContentRect.intersected(targetArea);
 
253
        if (!currentContentRect.contains(targetIntersection)
 
254
            && (qAbs(endVisibleContentRect.top() - currentContentRect.top()) >= 40
 
255
            || qAbs(endVisibleContentRect.left() - currentContentRect.left()) >= 40))
 
256
            zoomAction = NoZoom;
 
257
        else
 
258
            zoomAction = ZoomBack;
 
259
    } else if (fuzzyCompare(targetScale, m_zoomOutScale, 0.01))
 
260
        zoomAction = ZoomBack;
 
261
    else if (targetScale < currentScale)
 
262
        zoomAction = ZoomOut;
 
263
 
 
264
    switch (zoomAction) {
 
265
    case ZoomIn:
 
266
        m_scaleStack.append(ScaleStackItem(currentScale, m_viewportItem->contentPos().x() / currentScale));
 
267
        m_zoomOutScale = targetScale;
 
268
        break;
 
269
    case ZoomBack: {
 
270
        if (m_scaleStack.isEmpty()) {
 
271
            targetScale = m_controller->minimumContentsScale() * m_controller->devicePixelRatio();
 
272
            endPosition.setY(hotspot.y() - viewportHotspot.y() / targetScale);
 
273
            endPosition.setX(0);
 
274
            m_zoomOutScale = 0;
 
275
        } else {
 
276
            ScaleStackItem lastScale = m_scaleStack.takeLast();
 
277
            targetScale = lastScale.scale;
 
278
            // Recalculate endPosition and clamp it according to the new scale.
 
279
            endPosition.setY(hotspot.y() - viewportHotspot.y() / targetScale);
 
280
            endPosition.setX(lastScale.xPosition);
 
281
        }
 
282
        endPosition = m_controller->clampViewportToContents(endPosition, targetScale);
 
283
        endVisibleContentRect = QRectF(endPosition, viewportRect.size() / targetScale);
 
284
        break;
 
285
    }
 
286
    case ZoomOut:
 
287
        // Unstack all scale-levels deeper than the new level, so a zoom-back won't end up zooming in.
 
288
        while (!m_scaleStack.isEmpty() && m_scaleStack.last().scale >= targetScale)
 
289
            m_scaleStack.removeLast();
 
290
        m_zoomOutScale = targetScale;
 
291
        break;
 
292
    case NoZoom:
 
293
        break;
 
294
    }
 
295
 
 
296
    animateContentRectVisible(endVisibleContentRect);
 
297
}
 
298
 
 
299
void PageViewportControllerClientQt::clearRelativeZoomState()
 
300
{
 
301
    m_zoomOutScale = 0;
 
302
    m_scaleStack.clear();
 
303
}
 
304
 
 
305
QRectF PageViewportControllerClientQt::nearestValidVisibleContentsRect() const
 
306
{
 
307
    float targetScale = m_controller->innerBoundedViewportScale(m_pageItem->contentsScale());
 
308
 
 
309
    const QRectF viewportRect = m_viewportItem->boundingRect();
 
310
    QPointF viewportHotspot = viewportRect.center();
 
311
    // Keep the center at the position of the old center, and substract viewportHotspot / targetScale to get the top left position.
 
312
    QPointF endPosition = m_viewportItem->mapToWebContent(viewportHotspot) - viewportHotspot / targetScale;
 
313
 
 
314
    endPosition = m_controller->clampViewportToContents(endPosition, targetScale);
 
315
    return QRectF(endPosition, viewportRect.size() / targetScale);
 
316
}
 
317
 
 
318
void PageViewportControllerClientQt::setViewportPosition(const FloatPoint& contentsPoint)
 
319
{
 
320
    QPointF newPosition((m_pageItem->pos() + QPointF(contentsPoint)) * m_pageItem->contentsScale());
 
321
    m_viewportItem->setContentPos(newPosition);
 
322
    updateViewportController();
 
323
}
 
324
 
 
325
void PageViewportControllerClientQt::setContentsScale(float localScale, bool treatAsInitialValue)
 
326
{
 
327
    if (treatAsInitialValue) {
 
328
        clearRelativeZoomState();
 
329
        setContentRectVisiblePositionAtScale(QPointF(), localScale);
 
330
    } else
 
331
        scaleContent(localScale);
 
332
}
 
333
 
 
334
void PageViewportControllerClientQt::setContentsRectToNearestValidBounds()
 
335
{
 
336
    float targetScale = m_controller->innerBoundedViewportScale(m_pageItem->contentsScale());
 
337
    setContentRectVisiblePositionAtScale(nearestValidVisibleContentsRect().topLeft(), targetScale);
 
338
    updateViewportController();
 
339
}
 
340
 
 
341
void PageViewportControllerClientQt::didResumeContent()
 
342
{
 
343
    // Make sure that tiles all around the viewport will be requested.
 
344
    updateViewportController();
 
345
}
 
346
 
 
347
bool PageViewportControllerClientQt::scrollAnimationActive() const
 
348
{
 
349
    return m_viewportItem->isFlicking();
 
350
}
 
351
 
 
352
bool PageViewportControllerClientQt::panGestureActive() const
 
353
{
 
354
    return m_controller->hadUserInteraction() && m_viewportItem->isDragging();
 
355
}
 
356
 
 
357
void PageViewportControllerClientQt::panGestureStarted(const QPointF& position, qint64 eventTimestampMillis)
 
358
{
 
359
    // This can only happen as a result of a user interaction.
 
360
    ASSERT(m_controller->hadUserInteraction());
 
361
 
 
362
    m_viewportItem->handleFlickableMousePress(position, eventTimestampMillis);
 
363
    m_lastPinchCenterInViewportCoordinates = position;
 
364
}
 
365
 
 
366
void PageViewportControllerClientQt::panGestureRequestUpdate(const QPointF& position, qint64 eventTimestampMillis)
 
367
{
 
368
    m_viewportItem->handleFlickableMouseMove(position, eventTimestampMillis);
 
369
    m_lastPinchCenterInViewportCoordinates = position;
 
370
}
 
371
 
 
372
void PageViewportControllerClientQt::panGestureEnded(const QPointF& position, qint64 eventTimestampMillis)
 
373
{
 
374
    m_viewportItem->handleFlickableMouseRelease(position, eventTimestampMillis);
 
375
    m_lastPinchCenterInViewportCoordinates = position;
 
376
}
 
377
 
 
378
void PageViewportControllerClientQt::panGestureCancelled()
 
379
{
 
380
    // Reset the velocity samples of the flickable.
 
381
    // This should only be called by the recognizer if we have a recognized
 
382
    // pan gesture and receive a touch event with multiple touch points
 
383
    // (ie. transition to a pinch gesture) as it does not move the content
 
384
    // back inside valid bounds.
 
385
    // When the pinch gesture ends, the content is positioned and scaled
 
386
    // back to valid boundaries.
 
387
    m_viewportItem->cancelFlick();
 
388
}
 
389
 
 
390
bool PageViewportControllerClientQt::scaleAnimationActive() const
 
391
{
 
392
    return m_scaleAnimation->state() == QAbstractAnimation::Running;
 
393
}
 
394
 
 
395
void PageViewportControllerClientQt::cancelScrollAnimation()
 
396
{
 
397
    if (!scrollAnimationActive())
 
398
        return;
 
399
 
 
400
    // If the pan gesture recognizer receives a touch begin event
 
401
    // during an ongoing kinetic scroll animation of a previous
 
402
    // pan gesture, the animation is stopped and the content is
 
403
    // immediately positioned back to valid boundaries.
 
404
 
 
405
    m_viewportItem->cancelFlick();
 
406
    setContentsRectToNearestValidBounds();
 
407
}
 
408
 
 
409
void PageViewportControllerClientQt::interruptScaleAnimation()
 
410
{
 
411
    // This interrupts the scale animation exactly where it is, even if it is out of bounds.
 
412
    m_scaleAnimation->stop();
 
413
}
 
414
 
 
415
bool PageViewportControllerClientQt::pinchGestureActive() const
 
416
{
 
417
    return m_controller->hadUserInteraction() && (m_pinchStartScale > 0);
 
418
}
 
419
 
 
420
void PageViewportControllerClientQt::pinchGestureStarted(const QPointF& pinchCenterInViewportCoordinates)
 
421
{
 
422
    // This can only happen as a result of a user interaction.
 
423
    ASSERT(m_controller->hadUserInteraction());
 
424
 
 
425
    if (!m_controller->allowsUserScaling())
 
426
        return;
 
427
 
 
428
    clearRelativeZoomState();
 
429
 
 
430
    m_controller->suspendContent();
 
431
 
 
432
    m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates;
 
433
    m_pinchStartScale = m_pageItem->contentsScale();
 
434
}
 
435
 
 
436
void PageViewportControllerClientQt::pinchGestureRequestUpdate(const QPointF& pinchCenterInViewportCoordinates, qreal totalScaleFactor)
 
437
{
 
438
    ASSERT(m_controller->hasSuspendedContent());
 
439
 
 
440
    if (!m_controller->allowsUserScaling())
 
441
        return;
 
442
 
 
443
    //  Changes of the center position should move the page even if the zoom factor does not change.
 
444
    const qreal pinchScale = m_pinchStartScale * totalScaleFactor;
 
445
 
 
446
    // Allow zooming out beyond mimimum scale on pages that do not explicitly disallow it.
 
447
    const qreal targetScale = m_controller->outerBoundedViewportScale(pinchScale);
 
448
 
 
449
    scaleContent(targetScale, m_viewportItem->mapToWebContent(pinchCenterInViewportCoordinates));
 
450
 
 
451
    const QPointF positionDiff = pinchCenterInViewportCoordinates - m_lastPinchCenterInViewportCoordinates;
 
452
    m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates;
 
453
 
 
454
    m_viewportItem->setContentPos(m_viewportItem->contentPos() - positionDiff);
 
455
}
 
456
 
 
457
void PageViewportControllerClientQt::pinchGestureEnded()
 
458
{
 
459
    ASSERT(m_controller->hasSuspendedContent());
 
460
 
 
461
    if (!m_controller->allowsUserScaling())
 
462
        return;
 
463
 
 
464
    m_pinchStartScale = -1;
 
465
 
 
466
    // This will take care of resuming the content, even if no animation was performed.
 
467
    animateContentRectVisible(nearestValidVisibleContentsRect());
 
468
}
 
469
 
 
470
void PageViewportControllerClientQt::pinchGestureCancelled()
 
471
{
 
472
    m_pinchStartScale = -1;
 
473
    m_controller->resumeContent();
 
474
}
 
475
 
 
476
void PageViewportControllerClientQt::didChangeContentsSize(const IntSize& newSize)
 
477
{
 
478
    m_pageItem->setContentsSize(QSizeF(newSize));
 
479
 
 
480
    // Emit for testing purposes, so that it can be verified that
 
481
    // we didn't do scale adjustment.
 
482
    emit m_viewportItem->experimental()->test()->contentsScaleCommitted();
 
483
 
 
484
    if (!m_controller->hasSuspendedContent())
 
485
        setContentsRectToNearestValidBounds();
 
486
}
 
487
 
 
488
void PageViewportControllerClientQt::didChangeVisibleContents()
 
489
{
 
490
    qreal scale = m_pageItem->contentsScale();
 
491
 
 
492
    if (scale != m_lastCommittedScale)
 
493
        emit m_viewportItem->experimental()->test()->contentsScaleCommitted();
 
494
    m_lastCommittedScale = scale;
 
495
 
 
496
    // Ensure that updatePaintNode is always called before painting.
 
497
    m_pageItem->update();
 
498
}
 
499
 
 
500
void PageViewportControllerClientQt::didChangeViewportAttributes()
 
501
{
 
502
    clearRelativeZoomState();
 
503
    emit m_viewportItem->experimental()->test()->viewportChanged();
 
504
}
 
505
 
 
506
void PageViewportControllerClientQt::updateViewportController(const QPointF& trajectory)
 
507
{
 
508
    FloatPoint viewportPos = m_viewportItem->mapToWebContent(QPointF());
 
509
    m_controller->didChangeContentsVisibility(viewportPos, m_pageItem->contentsScale(), trajectory);
 
510
}
 
511
 
 
512
void PageViewportControllerClientQt::scaleContent(qreal itemScale, const QPointF& centerInCSSCoordinates)
 
513
{
 
514
    QPointF oldPinchCenterOnViewport = m_viewportItem->mapFromWebContent(centerInCSSCoordinates);
 
515
    m_pageItem->setContentsScale(itemScale);
 
516
    QPointF newPinchCenterOnViewport = m_viewportItem->mapFromWebContent(centerInCSSCoordinates);
 
517
    m_viewportItem->setContentPos(m_viewportItem->contentPos() + (newPinchCenterOnViewport - oldPinchCenterOnViewport));
 
518
}
 
519
 
 
520
float PageViewportControllerClientQt::viewportScaleForRect(const QRectF& rect) const
 
521
{
 
522
    return static_cast<float>(m_viewportItem->width()) / static_cast<float>(rect.width());
 
523
}
 
524
 
 
525
} // namespace WebKit
 
526
 
 
527
#include "moc_PageViewportControllerClientQt.cpp"