/* Copyright (C) 2011 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 library 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 library; 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 "../util.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include static WKContextRef webContext() { static WKContextRef result = WKContextCreate(); return result; } static WKPageGroupRef createWebPageGroup(const QString& name) { WKPageGroupRef pageGroup =WKPageGroupCreateWithIdentifier(WKStringCreateWithQString(name)); WKPreferencesRef preferences = WKPageGroupGetPreferences(pageGroup); WKPreferencesSetAcceleratedCompositingEnabled(preferences, true); WKPreferencesSetFrameFlatteningEnabled(preferences, true); return pageGroup; } static WKPageGroupRef webPageGroup(const QString& name) { static WKPageGroupRef result = createWebPageGroup(name); return result; } class WebView : public QObject, public QRawWebViewClient { Q_OBJECT public: WebView(const QSize& size, bool transparent = false) { m_webView = new QRawWebView(webContext(), webPageGroup(QString()), this); m_webView->setTransparentBackground(transparent); m_webView->create(); WKPageLoaderClient loaderClient; memset(&loaderClient, 0, sizeof(WKPageLoaderClient)); loaderClient.version = kWKPageLoaderClientCurrentVersion; loaderClient.clientInfo = this; loaderClient.didLayout = WebView::didLayout; WKPageSetPageLoaderClient(m_webView->pageRef(), &loaderClient); WKPageListenForLayoutMilestones(m_webView->pageRef(), kWKDidFirstVisuallyNonEmptyLayout); WKPageSetUseFixedLayout(m_webView->pageRef(), true); m_webView->setSize(size); m_webView->setFocused(true); m_webView->setVisible(true); m_webView->setActive(true); } ~WebView() { delete m_webView; } void load(const QString& html) { m_frameLoaded = false; WKPageLoadURL(m_webView->pageRef(), WKURLCreateWithUTF8CString(html.toLocal8Bit().data())); QVERIFY(::waitForSignal(this, SIGNAL(loaded()), 5000)); } void setDrawBackground(bool value) { m_webView->setDrawBackground(value); } void setTransparentBackground(bool value) { m_webView->setTransparentBackground(value); } virtual void viewNeedsDisplay(const QRect&) { m_webView->paint(QMatrix4x4(), 1, 0); } virtual void viewRequestedScroll(const QPoint&) { } virtual void viewProcessCrashed() { } virtual void viewProcessRelaunched() { } virtual void viewContentSizeChanged(const QSize&) { } virtual void viewRequestedCursorOverride(const QCursor&) { } virtual void doneWithKeyEvent(const QKeyEvent*, bool wasHandled) { } virtual void doneWithTouchEvent(const QTouchEvent*, bool wasHandled) { } void frameLoaded() { m_frameLoaded = true; WKPageForceRepaint(m_webView->pageRef(), this, finishForceRepaint); } void onRepaintDone() { emit loaded(); } static void finishForceRepaint(WKErrorRef, void* context) { static_cast(context)->onRepaintDone(); } static void didLayout(WKPageRef page, WKLayoutMilestones milestones, WKTypeRef userData, const void *clientInfo) { static_cast(const_cast(clientInfo))->frameLoaded(); } Q_SIGNALS: void loaded(); private: QRawWebView* m_webView; bool m_frameLoaded; }; static bool compareImages(const QImage& i1, const QImage& i2, int count) { if (i1.size() != i2.size()) return false; for (int x = 0; x < count; ++x) { for (int y = 0; y < count; ++y) { QPoint point(x * i1.width() / count, y * i1.height() / count); if (i1.pixel(point) != i2.pixel(point)) return false; } } return true; } class tst_qrawwebview : public QObject { Q_OBJECT public: tst_qrawwebview() : m_resourceDir(QString::fromLatin1(TESTS_SOURCE_DIR "/html/resources")) , m_baseUrl(QUrl::fromLocalFile(TESTS_SOURCE_DIR "/html").toString()) { addQtWebProcessToPath(); } private Q_SLOTS: void paint() { run(&tst_qrawwebview::doPaint, m_resourceDir + "/qwkview_paint.png"); } void noBackground1() { run(&tst_qrawwebview::doNoBackground1, m_resourceDir + "/qwkview_noBackground1.png"); } void noBackground2() { run(&tst_qrawwebview::doNoBackground2, m_resourceDir + "/qwkview_noBackground1.png"); } void noBackground3() { run(&tst_qrawwebview::doNoBackground3, m_resourceDir + "/qwkview_noBackground3.png"); } private: const QString m_resourceDir; const QString m_baseUrl; void doPaint(const QSize& size); void doNoBackground1(const QSize& size); void doNoBackground2(const QSize& size); void doNoBackground3(const QSize& size); typedef void (tst_qrawwebview::*PaintMethod)(const QSize& size); void run(PaintMethod, const QString& expectation); }; void tst_qrawwebview::doPaint(const QSize& size) { WebView view(size); view.load(m_baseUrl + "/redsquare.html"); } void tst_qrawwebview::doNoBackground1(const QSize& size) { WebView view(size, true); view.load(m_baseUrl + "/redsquare.html"); view.load(m_baseUrl + "/bluesquare.html"); } void tst_qrawwebview::doNoBackground2(const QSize& size) { WebView view1(size, true); view1.load(m_baseUrl + "/redsquare.html"); WebView view2(size, true); view2.load(m_baseUrl + "/bluesquare.html"); } void tst_qrawwebview::doNoBackground3(const QSize& size) { WebView view1(size, false); view1.load(m_baseUrl + "/redsquare.html"); WebView view2(size, true); view2.load(m_baseUrl + "/bluesquare.html"); } void tst_qrawwebview::run(PaintMethod method, const QString& expectation) { QWindow window; window.setSurfaceType(QSurface::OpenGLSurface); window.setGeometry(0, 0, 200, 200); window.create(); QOpenGLContext context; context.create(); context.makeCurrent(&window); glViewport(0, 0, window.size().width(), window.size().height()); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); (this->*method)(window.size()); QImage image(window.size(), QImage::Format_ARGB32_Premultiplied); glReadPixels(0, 0, window.size().width(), window.size().height(), GL_RGBA, GL_UNSIGNED_BYTE, image.bits()); QVERIFY(compareImages(QImage(expectation), image.rgbSwapped(), 5)); } QTEST_MAIN(tst_qrawwebview) #include "tst_qrawwebview.moc"