C++程序  |  816行  |  21.09 KB

/*
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this program; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "qwkpage.h"
#include "qwkpage_p.h"

#include "qwkpreferences_p.h"

#include "ChunkedUpdateDrawingAreaProxy.h"
#include "ClientImpl.h"
#include "qgraphicswkview.h"
#include "qwkcontext.h"
#include "qwkcontext_p.h"
#include "qwkhistory.h"
#include "qwkhistory_p.h"
#include "FindIndicator.h"
#include "LocalizedStrings.h"
#include "NativeWebKeyboardEvent.h"
#include "NativeWebMouseEvent.h"
#include "NotImplemented.h"
#include "TiledDrawingAreaProxy.h"
#include "WebContext.h"
#include "WebContextMenuProxyQt.h"
#include "WebEventFactoryQt.h"
#include "WebPopupMenuProxyQt.h"
#include "WKStringQt.h"
#include "WKURLQt.h"
#include "ViewportArguments.h"
#include <QAction>
#include <QApplication>
#include <QGraphicsSceneMouseEvent>
#include <QStyle>
#include <QTouchEvent>
#include <QtDebug>
#include <WebCore/Cursor.h>
#include <WebCore/FloatRect.h>
#include <WebCore/NotImplemented.h>
#include <WebKit2/WKFrame.h>
#include <WebKit2/WKPageGroup.h>
#include <WebKit2/WKRetainPtr.h>

using namespace WebKit;
using namespace WebCore;

static WebCore::ContextMenuAction contextMenuActionForWebAction(QWKPage::WebAction action)
{
    switch (action) {
    case QWKPage::OpenLink:
        return WebCore::ContextMenuItemTagOpenLink;
    case QWKPage::OpenLinkInNewWindow:
        return WebCore::ContextMenuItemTagOpenLinkInNewWindow;
    case QWKPage::CopyLinkToClipboard:
        return WebCore::ContextMenuItemTagCopyLinkToClipboard;
    case QWKPage::OpenImageInNewWindow:
        return WebCore::ContextMenuItemTagOpenImageInNewWindow;
    case QWKPage::Cut:
        return WebCore::ContextMenuItemTagCut;
    case QWKPage::Copy:
        return WebCore::ContextMenuItemTagCopy;
    case QWKPage::Paste:
        return WebCore::ContextMenuItemTagPaste;
    case QWKPage::SelectAll:
        return WebCore::ContextMenuItemTagSelectAll;
    default:
        ASSERT(false);
        break;
    }
    return WebCore::ContextMenuItemTagNoAction;
}

QWKPagePrivate::QWKPagePrivate(QWKPage* qq, QWKContext* c)
    : q(qq)
    , view(0)
    , context(c)
    , preferences(0)
    , createNewPageFn(0)
    , backingStoreType(QGraphicsWKView::Simple)
    , isConnectedToEngine(true)
{
    memset(actions, 0, sizeof(actions));
    page = context->d->context->createWebPage(this, 0);
    history = QWKHistoryPrivate::createHistory(page->backForwardList());
}

QWKPagePrivate::~QWKPagePrivate()
{
    page->close();
    delete history;
}

void QWKPagePrivate::init(QGraphicsItem* view, QGraphicsWKView::BackingStoreType backingStoreType)
{
    this->view = view;
    this->backingStoreType = backingStoreType;
    page->initializeWebPage();
}

void QWKPagePrivate::setCursor(const WebCore::Cursor& cursor)
{
#ifndef QT_NO_CURSOR
    emit q->cursorChanged(*cursor.platformCursor());
#endif
}

void QWKPagePrivate::setViewportArguments(const ViewportArguments& args)
{
    viewportArguments = args;
    emit q->viewportChangeRequested();
}

PassOwnPtr<DrawingAreaProxy> QWKPagePrivate::createDrawingAreaProxy()
{
    // FIXME: We should avoid this cast by decoupling the view from the page.
    QGraphicsWKView* wkView = static_cast<QGraphicsWKView*>(view);

#if ENABLE(TILED_BACKING_STORE)
    if (backingStoreType == QGraphicsWKView::Tiled)
        return TiledDrawingAreaProxy::create(wkView, page.get());
#endif
    return ChunkedUpdateDrawingAreaProxy::create(wkView, page.get());
}

void QWKPagePrivate::setViewNeedsDisplay(const WebCore::IntRect& rect)
{
    view->update(QRect(rect));
}

void QWKPagePrivate::displayView()
{
    // FIXME: Implement.
}

void QWKPagePrivate::scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset)
{
    // FIXME: Implement.
}

WebCore::IntSize QWKPagePrivate::viewSize()
{
    // FIXME: Implement.
    return WebCore::IntSize();
}

bool QWKPagePrivate::isViewWindowActive()
{
    return view && view->isActive();
}

bool QWKPagePrivate::isViewFocused()
{
    return view && view->hasFocus();
}

bool QWKPagePrivate::isViewVisible()
{
    return view && view->isVisible();
}

bool QWKPagePrivate::isViewInWindow()
{
    // FIXME: Implement.
    return true;
}

void QWKPagePrivate::enterAcceleratedCompositingMode(const LayerTreeContext&)
{
    // FIXME: Implement.
}

void QWKPagePrivate::exitAcceleratedCompositingMode()
{
    // FIXME: Implement.
}

void QWKPagePrivate::pageDidRequestScroll(const IntPoint& point)
{
    emit q->scrollRequested(point.x(), point.y());
}

void QWKPagePrivate::didChangeContentsSize(const IntSize& newSize)
{
    emit q->contentsSizeChanged(QSize(newSize));
}

void QWKPagePrivate::toolTipChanged(const String&, const String& newTooltip)
{
    emit q->toolTipChanged(QString(newTooltip));
}

void QWKPagePrivate::registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo)
{
}

void QWKPagePrivate::clearAllEditCommands()
{
}

bool QWKPagePrivate::canUndoRedo(WebPageProxy::UndoOrRedo)
{
    return false;
}

void QWKPagePrivate::executeUndoRedo(WebPageProxy::UndoOrRedo)
{
}

FloatRect QWKPagePrivate::convertToDeviceSpace(const FloatRect& rect)
{
    return rect;
}

IntRect QWKPagePrivate::windowToScreen(const IntRect& rect)
{
    return rect;
}

FloatRect QWKPagePrivate::convertToUserSpace(const FloatRect& rect)
{
    return rect;
}

void QWKPagePrivate::selectionChanged(bool, bool, bool, bool)
{
}

void QWKPagePrivate::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool)
{
}

PassRefPtr<WebPopupMenuProxy> QWKPagePrivate::createPopupMenuProxy(WebPageProxy*)
{
    return WebPopupMenuProxyQt::create();
}

PassRefPtr<WebContextMenuProxy> QWKPagePrivate::createContextMenuProxy(WebPageProxy*)
{
    return WebContextMenuProxyQt::create(q);
}

void QWKPagePrivate::setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut)
{
}

void QWKPagePrivate::didCommitLoadForMainFrame(bool useCustomRepresentation)
{
}

void QWKPagePrivate::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference&)
{
}

void QWKPagePrivate::flashBackingStoreUpdates(const Vector<IntRect>&)
{
    notImplemented();
}

void QWKPagePrivate::paint(QPainter* painter, QRect area)
{
    if (page->isValid() && page->drawingArea())
        page->drawingArea()->paint(IntRect(area), painter);
    else
        painter->fillRect(area, Qt::white);
}

void QWKPagePrivate::keyPressEvent(QKeyEvent* ev)
{
    page->handleKeyboardEvent(NativeWebKeyboardEvent(ev));
}

void QWKPagePrivate::keyReleaseEvent(QKeyEvent* ev)
{
    page->handleKeyboardEvent(NativeWebKeyboardEvent(ev));
}

void QWKPagePrivate::mouseMoveEvent(QGraphicsSceneMouseEvent* ev)
{
    // For some reason mouse press results in mouse hover (which is
    // converted to mouse move for WebKit). We ignore these hover
    // events by comparing lastPos with newPos.
    // NOTE: lastPos from the event always comes empty, so we work
    // around that here.
    static QPointF lastPos = QPointF();
    if (lastPos == ev->pos())
        return;
    lastPos = ev->pos();

    page->handleMouseEvent(NativeWebMouseEvent(ev, 0));
}

void QWKPagePrivate::mousePressEvent(QGraphicsSceneMouseEvent* ev)
{
    if (tripleClickTimer.isActive() && (ev->pos() - tripleClick).manhattanLength() < QApplication::startDragDistance()) {
        page->handleMouseEvent(NativeWebMouseEvent(ev, 3));
        return;
    }

    page->handleMouseEvent(NativeWebMouseEvent(ev, 1));
}

void QWKPagePrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev)
{
    page->handleMouseEvent(NativeWebMouseEvent(ev, 0));
}

void QWKPagePrivate::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev)
{
    page->handleMouseEvent(NativeWebMouseEvent(ev, 2));

    tripleClickTimer.start(QApplication::doubleClickInterval(), q);
    tripleClick = ev->pos().toPoint();
}

void QWKPagePrivate::wheelEvent(QGraphicsSceneWheelEvent* ev)
{
    WebWheelEvent wheelEvent = WebEventFactory::createWebWheelEvent(ev);
    page->handleWheelEvent(wheelEvent);
}

void QWKPagePrivate::updateAction(QWKPage::WebAction action)
{
#ifdef QT_NO_ACTION
    Q_UNUSED(action)
#else
    QAction* a = actions[action];
    if (!a)
        return;

    RefPtr<WebKit::WebFrameProxy> mainFrame = page->mainFrame();
    if (!mainFrame)
        return;

    bool enabled = a->isEnabled();
    bool checked = a->isChecked();

    switch (action) {
    case QWKPage::Back:
        enabled = page->canGoBack();
        break;
    case QWKPage::Forward:
        enabled = page->canGoForward();
        break;
    case QWKPage::Stop:
        enabled = !(WebFrameProxy::LoadStateFinished == mainFrame->loadState());
        break;
    case QWKPage::Reload:
        enabled = (WebFrameProxy::LoadStateFinished == mainFrame->loadState());
        break;
    default:
        break;
    }

    a->setEnabled(enabled);

    if (a->isCheckable())
        a->setChecked(checked);
#endif // QT_NO_ACTION
}

void QWKPagePrivate::updateNavigationActions()
{
    updateAction(QWKPage::Back);
    updateAction(QWKPage::Forward);
    updateAction(QWKPage::Stop);
    updateAction(QWKPage::Reload);
}

#ifndef QT_NO_ACTION
void QWKPagePrivate::_q_webActionTriggered(bool checked)
{
    QAction* a = qobject_cast<QAction*>(q->sender());
    if (!a)
        return;
    QWKPage::WebAction action = static_cast<QWKPage::WebAction>(a->data().toInt());
    q->triggerAction(action, checked);
}
#endif // QT_NO_ACTION

void QWKPagePrivate::touchEvent(QTouchEvent* event)
{
#if ENABLE(TOUCH_EVENTS)
    WebTouchEvent touchEvent = WebEventFactory::createWebTouchEvent(event);
    page->handleTouchEvent(touchEvent);
#else
    event->ignore();
#endif
}

void QWKPagePrivate::didRelaunchProcess()
{
    QGraphicsWKView* wkView = static_cast<QGraphicsWKView*>(view);
    if (wkView)
        q->setViewportSize(wkView->size().toSize());

    isConnectedToEngine = true;
    emit q->engineConnectionChanged(true);
}

void QWKPagePrivate::processDidCrash()
{
    isConnectedToEngine = false;
    emit q->engineConnectionChanged(false);
}

QWKPage::QWKPage(QWKContext* context)
    : d(new QWKPagePrivate(this, context))
{
    WKPageLoaderClient loadClient = {
        0,      /* version */
        this,   /* clientInfo */
        qt_wk_didStartProvisionalLoadForFrame,
        qt_wk_didReceiveServerRedirectForProvisionalLoadForFrame,
        qt_wk_didFailProvisionalLoadWithErrorForFrame,
        qt_wk_didCommitLoadForFrame,
        qt_wk_didFinishDocumentLoadForFrame,
        qt_wk_didFinishLoadForFrame,
        qt_wk_didFailLoadWithErrorForFrame,
        0, /* didSameDocumentNavigationForFrame */
        qt_wk_didReceiveTitleForFrame,
        qt_wk_didFirstLayoutForFrame,
        qt_wk_didFirstVisuallyNonEmptyLayoutForFrame,
        qt_wk_didRemoveFrameFromHierarchy,
        0, /* didDisplayInsecureContentForFrame */
        0, /* didRunInsecureContentForFrame */
        0, /* canAuthenticateAgainstProtectionSpaceInFrame */
        0, /* didReceiveAuthenticationChallengeInFrame */
        qt_wk_didStartProgress,
        qt_wk_didChangeProgress,
        qt_wk_didFinishProgress,
        qt_wk_didBecomeUnresponsive,
        qt_wk_didBecomeResponsive,
        0,  /* processDidCrash */
        0,  /* didChangeBackForwardList */
        0   /* shouldGoToBackForwardListItem */
    };
    WKPageSetPageLoaderClient(pageRef(), &loadClient);

    WKPageUIClient uiClient = {
        0,      /* version */
        this,   /* clientInfo */
        qt_wk_createNewPage,
        qt_wk_showPage,
        qt_wk_close,
        qt_wk_takeFocus,
        0,  /* focus */
        0,  /* unfocus */
        qt_wk_runJavaScriptAlert,
        0,  /* runJavaScriptConfirm */
        0,  /* runJavaScriptPrompt */
        qt_wk_setStatusText,
        0,  /* mouseDidMoveOverElement */
        0,  /* missingPluginButtonClicked */
        0,  /* didNotHandleKeyEvent */
        0,  /* toolbarsAreVisible */
        0,  /* setToolbarsAreVisible */
        0,  /* menuBarIsVisible */
        0,  /* setMenuBarIsVisible */
        0,  /* statusBarIsVisible */
        0,  /* setStatusBarIsVisible */
        0,  /* isResizable */
        0,  /* setIsResizable */
        0,  /* getWindowFrame */
        0,  /* setWindowFrame */
        0,  /* runBeforeUnloadConfirmPanel */
        0,  /* didDraw */
        0,  /* pageDidScroll */
        0,  /* exceededDatabaseQuota */
        0,  /* runOpenPanel */
        0,  /* decidePolicyForGeolocationPermissionRequest */
        0,  /* headerHeight */
        0,  /* footerHeight */
        0,  /* drawHeader */
        0,  /* drawFooter */
        0,  /* printFrame */
        0,  /* runModal */
        0,   /* didCompleteRubberBandForMainFrame */
        0    /* saveDataToFileInDownloadsFolder */
    };
    WKPageSetPageUIClient(pageRef(), &uiClient);
}

QWKPage::~QWKPage()
{
    delete d;
}

QWKPage::ViewportAttributes::ViewportAttributes()
    : d(0)
    , m_initialScaleFactor(-1.0)
    , m_minimumScaleFactor(-1.0)
    , m_maximumScaleFactor(-1.0)
    , m_devicePixelRatio(-1.0)
    , m_isUserScalable(true)
    , m_isValid(false)
{

}

QWKPage::ViewportAttributes::ViewportAttributes(const QWKPage::ViewportAttributes& other)
    : d(other.d)
    , m_initialScaleFactor(other.m_initialScaleFactor)
    , m_minimumScaleFactor(other.m_minimumScaleFactor)
    , m_maximumScaleFactor(other.m_maximumScaleFactor)
    , m_devicePixelRatio(other.m_devicePixelRatio)
    , m_isUserScalable(other.m_isUserScalable)
    , m_isValid(other.m_isValid)
    , m_size(other.m_size)
{

}

QWKPage::ViewportAttributes::~ViewportAttributes()
{

}

QWKPage::ViewportAttributes& QWKPage::ViewportAttributes::operator=(const QWKPage::ViewportAttributes& other)
{
    if (this != &other) {
        d = other.d;
        m_initialScaleFactor = other.m_initialScaleFactor;
        m_minimumScaleFactor = other.m_minimumScaleFactor;
        m_maximumScaleFactor = other.m_maximumScaleFactor;
        m_devicePixelRatio = other.m_devicePixelRatio;
        m_isUserScalable = other.m_isUserScalable;
        m_isValid = other.m_isValid;
        m_size = other.m_size;
    }

    return *this;
}

QWKPage::ViewportAttributes QWKPage::viewportAttributesForSize(const QSize& availableSize) const
{
    static int desktopWidth = 980;
    static int deviceDPI = 160;

    ViewportAttributes result;

     if (availableSize.isEmpty())
         return result; // Returns an invalid instance.

    // FIXME: Add a way to get these data via the platform plugin and fall back
    // to the size of the view.
    int deviceWidth = 480;
    int deviceHeight = 864;

    WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(d->viewportArguments, desktopWidth, deviceWidth, deviceHeight, deviceDPI, availableSize);

    result.m_isValid = true;
    result.m_size = conf.layoutSize;
    result.m_initialScaleFactor = conf.initialScale;
    result.m_minimumScaleFactor = conf.minimumScale;
    result.m_maximumScaleFactor = conf.maximumScale;
    result.m_devicePixelRatio = conf.devicePixelRatio;
    result.m_isUserScalable = static_cast<bool>(conf.userScalable);

    return result;
}

void QWKPage::setActualVisibleContentsRect(const QRect& rect) const
{
#if ENABLE(TILED_BACKING_STORE)
    d->page->setActualVisibleContentRect(rect);
#endif
}

void QWKPage::timerEvent(QTimerEvent* ev)
{
    int timerId = ev->timerId();
    if (timerId == d->tripleClickTimer.timerId())
        d->tripleClickTimer.stop();
    else
        QObject::timerEvent(ev);
}

WKPageRef QWKPage::pageRef() const
{
    return toAPI(d->page.get());
}

QWKContext* QWKPage::context() const
{
    return d->context;
}

QWKPreferences* QWKPage::preferences() const
{
    if (!d->preferences) {
        WKPageGroupRef pageGroupRef = WKPageGetPageGroup(pageRef());
        d->preferences = QWKPreferencesPrivate::createPreferences(pageGroupRef);
    }

    return d->preferences;
}

void QWKPage::setCreateNewPageFunction(CreateNewPageFn function)
{
    d->createNewPageFn = function;
}

void QWKPage::setCustomUserAgent(const QString& userAgent)
{
    WKRetainPtr<WKStringRef> wkUserAgent(WKStringCreateWithQString(userAgent));
    WKPageSetCustomUserAgent(pageRef(), wkUserAgent.get());
}

QString QWKPage::customUserAgent() const
{
    return WKStringCopyQString(WKPageCopyCustomUserAgent(pageRef()));
}

void QWKPage::load(const QUrl& url)
{
    WKRetainPtr<WKURLRef> wkurl(WKURLCreateWithQUrl(url));
    WKPageLoadURL(pageRef(), wkurl.get());
}

void QWKPage::setUrl(const QUrl& url)
{
    load(url);
}

QUrl QWKPage::url() const
{
    WKRetainPtr<WKFrameRef> frame = WKPageGetMainFrame(pageRef());
    if (!frame)
        return QUrl();
    return WKURLCopyQUrl(WKFrameCopyURL(frame.get()));
}

QString QWKPage::title() const
{
    return WKStringCopyQString(WKPageCopyTitle(pageRef()));
}

void QWKPage::setViewportSize(const QSize& size)
{
    if (d->page->drawingArea())
        d->page->drawingArea()->setSize(IntSize(size), IntSize());
}

qreal QWKPage::textZoomFactor() const
{
    return WKPageGetTextZoomFactor(pageRef());
}

void QWKPage::setTextZoomFactor(qreal zoomFactor)
{
    WKPageSetTextZoomFactor(pageRef(), zoomFactor);
}

qreal QWKPage::pageZoomFactor() const
{
    return WKPageGetPageZoomFactor(pageRef());
}

void QWKPage::setPageZoomFactor(qreal zoomFactor)
{
    WKPageSetPageZoomFactor(pageRef(), zoomFactor);
}

void QWKPage::setPageAndTextZoomFactors(qreal pageZoomFactor, qreal textZoomFactor)
{
    WKPageSetPageAndTextZoomFactors(pageRef(), pageZoomFactor, textZoomFactor);
}

QWKHistory* QWKPage::history() const
{
    return d->history;
}

void QWKPage::setResizesToContentsUsingLayoutSize(const QSize& targetLayoutSize)
{
#if ENABLE(TILED_BACKING_STORE)
    d->page->setResizesToContentsUsingLayoutSize(targetLayoutSize);
#endif
}

#ifndef QT_NO_ACTION
void QWKPage::triggerAction(WebAction webAction, bool)
{
    switch (webAction) {
    case Back:
        d->page->goBack();
        return;
    case Forward:
        d->page->goForward();
        return;
    case Stop:
        d->page->stopLoading();
        return;
    case Reload:
        d->page->reload(/* reloadFromOrigin */ true);
        return;
    default:
        break;
    }

    QAction* qtAction = action(webAction);
    WebKit::WebContextMenuItemData menuItemData(ActionType, contextMenuActionForWebAction(webAction), qtAction->text(), qtAction->isEnabled(), qtAction->isChecked());
    d->page->contextMenuItemSelected(menuItemData);
}
#endif // QT_NO_ACTION

#ifndef QT_NO_ACTION
QAction* QWKPage::action(WebAction action) const
{
    if (action == QWKPage::NoWebAction || action >= WebActionCount)
        return 0;

    if (d->actions[action])
        return d->actions[action];

    QString text;
    QIcon icon;
    QStyle* style = qobject_cast<QApplication*>(QCoreApplication::instance())->style();
    bool checkable = false;

    switch (action) {
    case OpenLink:
        text = contextMenuItemTagOpenLink();
        break;
    case OpenLinkInNewWindow:
        text = contextMenuItemTagOpenLinkInNewWindow();
        break;
    case CopyLinkToClipboard:
        text = contextMenuItemTagCopyLinkToClipboard();
        break;
    case OpenImageInNewWindow:
        text = contextMenuItemTagOpenImageInNewWindow();
        break;
    case Back:
        text = contextMenuItemTagGoBack();
        icon = style->standardIcon(QStyle::SP_ArrowBack);
        break;
    case Forward:
        text = contextMenuItemTagGoForward();
        icon = style->standardIcon(QStyle::SP_ArrowForward);
        break;
    case Stop:
        text = contextMenuItemTagStop();
        icon = style->standardIcon(QStyle::SP_BrowserStop);
        break;
    case Reload:
        text = contextMenuItemTagReload();
        icon = style->standardIcon(QStyle::SP_BrowserReload);
        break;
    case Cut:
        text = contextMenuItemTagCut();
        break;
    case Copy:
        text = contextMenuItemTagCopy();
        break;
    case Paste:
        text = contextMenuItemTagPaste();
        break;
    case SelectAll:
        text = contextMenuItemTagSelectAll();
        break;
    default:
        return 0;
        break;
    }

    if (text.isEmpty())
        return 0;

    QAction* a = new QAction(d->q);
    a->setText(text);
    a->setData(action);
    a->setCheckable(checkable);
    a->setIcon(icon);

    connect(a, SIGNAL(triggered(bool)), this, SLOT(_q_webActionTriggered(bool)));

    d->actions[action] = a;
    d->updateAction(action);
    return a;
}
#endif // QT_NO_ACTION

void QWKPage::findZoomableAreaForPoint(const QPoint& point)
{
    d->page->findZoomableAreaForPoint(point);
}

void QWKPagePrivate::didFindZoomableArea(const IntRect& area)
{
    emit q->zoomableAreaFound(QRect(area));
}

bool QWKPage::isConnectedToEngine() const
{
    return d->isConnectedToEngine;
}

#include "moc_qwkpage.cpp"