TEST(WebKitNix, WebViewTranslatedScaled) { // This test opens a webpage that contains a white background, no viewport // metatag and a red rectangle (20x20)px at (0,0) position. The viewport is // then translated to (10,10) position. After that it's applied a scale=2.0 // At this point we will have a red rectangle of (40x40)px at (10,10). const WKSize size = WKSizeMake(100, 100); ToolsNix::GLOffscreenBuffer offscreenBuffer(size.width, size.height); ASSERT_TRUE(offscreenBuffer.makeCurrent()); WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate()); WKRetainPtr<WKViewRef> view(AdoptWK, WKViewCreate(context.get(), 0)); Util::ForceRepaintClient forceRepaintClient(view.get()); forceRepaintClient.setClearColor(0, 0, 1, 1); const int delta = 10; WKViewSetUserViewportTranslation(view.get(), delta, delta); WKViewInitialize(view.get()); WKPageSetUseFixedLayout(WKViewGetPage(view.get()), true); WKViewSetSize(view.get(), size); glViewport(0, 0, size.width, size.height); forceRepaintClient.clear(); Util::PageLoader loader(view.get()); loader.waitForLoadURLAndRepaint("../nix/red-square"); for (double scale = 1.0; scale < 3.0; scale++) { WKViewSetContentScaleFactor(view.get(), scale); loader.forceRepaint(); ToolsNix::RGBAPixel outsideTheContent = offscreenBuffer.readPixelAtPoint(delta - 1, delta - 1); EXPECT_EQ(ToolsNix::RGBAPixel::blue(), outsideTheContent); ToolsNix::RGBAPixel squareTopLeft = offscreenBuffer.readPixelAtPoint(delta, delta); EXPECT_EQ(ToolsNix::RGBAPixel::red(), squareTopLeft); const int scaledSize = scale * 20; ToolsNix::RGBAPixel squareBottomRight = offscreenBuffer.readPixelAtPoint(delta + scaledSize - 1, delta + scaledSize - 1); EXPECT_EQ(ToolsNix::RGBAPixel::red(), squareBottomRight); ToolsNix::RGBAPixel outsideSquare = offscreenBuffer.readPixelAtPoint(delta + scaledSize, delta + scaledSize); EXPECT_EQ(ToolsNix::RGBAPixel::white(), outsideSquare); } }
TEST(WebKitNix, WebViewTranslated) { const WKSize size = WKSizeMake(100, 100); ToolsNix::GLOffscreenBuffer offscreenBuffer(size.width, size.height); ASSERT_TRUE(offscreenBuffer.makeCurrent()); WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate()); const int translationDelta = 20; NIXViewAutoPtr view(NIXViewCreate(context.get(), 0)); Util::ForceRepaintClient client(view.get()); client.setClearColor(0, 0, 1, 1); NIXMatrix transform = NIXMatrixMakeTranslation(translationDelta, translationDelta); NIXViewSetUserViewportTransformation(view.get(), &transform); NIXViewInitialize(view.get()); WKPageSetUseFixedLayout(NIXViewGetPage(view.get()), true); NIXViewSetSize(view.get(), size); glViewport(0, 0, size.width, size.height); glClearColor(0, 0, 1, 1); glClear(GL_COLOR_BUFFER_BIT); Util::PageLoader loader(view.get()); loader.waitForLoadURLAndRepaint("../nix/red-background"); // Note that glReadPixels [0, 0] is at the bottom-left of the buffer, so a diagonal // line from the top-left, to the bottom-right, will have X values going up and Y // values going down. We are testing this diagonal here. // Original background. ToolsNix::RGBAPixel sample[int(size.width * size.height)]; glReadPixels(0, 0, size.width, size.height, GL_RGBA, GL_UNSIGNED_BYTE, &sample); for (int x = 0, y = size.height - 1; x < translationDelta; x++, y--) { int index = y * size.height + x; EXPECT_EQ(ToolsNix::RGBAPixel::blue(), sample[index]) << "Error when checking for pixel (" << x << ", " << y << ")"; } // Red background page. for (int x = translationDelta, y = size.height - translationDelta - 1; x < size.width; x++, y--) { int index = y * size.height + x; EXPECT_EQ(ToolsNix::RGBAPixel::red(), sample[index]) << "Error when checking for pixel (" << x << ", " << y << ")"; } }
PlatformWebView::PlatformWebView(WKContextRef context, WKPageGroupRef pageGroup, WKPageRef /* relatedPage */, WKDictionaryRef options) : m_options(options) { WKRetainPtr<WKStringRef> useFixedLayoutKey(AdoptWK, WKStringCreateWithUTF8CString("UseFixedLayout")); m_usingFixedLayout = options ? WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(options, useFixedLayoutKey.get()))) : false; m_window = initEcoreEvas(); m_view = EWKViewCreate(context, pageGroup, ecore_evas_get(m_window), /* smart */ 0); WKPageSetUseFixedLayout(WKViewGetPage(EWKViewGetWKView(m_view)), m_usingFixedLayout); if (m_usingFixedLayout) resizeTo(800, 600); ewk_view_theme_set(m_view, TEST_THEME_DIR "/default.edj"); m_windowIsKey = false; evas_object_show(m_view); }
PlatformWebView::PlatformWebView(WKPageConfigurationRef configuration, const TestOptions& options) : m_options(options) { WKRetainPtr<WKStringRef> useFixedLayoutKey(AdoptWK, WKStringCreateWithUTF8CString("UseFixedLayout")); m_usingFixedLayout = options.useFixedLayout; m_window = initEcoreEvas(); WKContextRef context = WKPageConfigurationGetContext(configuration); m_view = EWKViewCreate(context, configuration, ecore_evas_get(m_window), /* smart */ 0); WKPageSetUseFixedLayout(WKViewGetPage(EWKViewGetWKView(m_view)), m_usingFixedLayout); if (m_usingFixedLayout) resizeTo(800, 600); ewk_view_theme_set(m_view, DEFAULT_THEME_DIR "/default.edj"); m_windowIsKey = false; evas_object_show(m_view); }
TEST(WebKit2, WKViewUserViewportToContents) { // This test creates a WKView and uses the WKViewUserViewportToContents // function to convert viewport coordinates to contents (page) coordinates. // It scrolls and scales around the contents and check if the coordinates // conversion math is right. WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate()); WKRetainPtr<WKViewRef> webView(AdoptWK, WKViewCreate(context.get(), 0)); WKViewInitialize(webView.get()); WKPageSetUseFixedLayout(WKViewGetPage(webView.get()), false); WKPoint out; // At scale 1.0 the viewport and contents coordinates should match. WKViewSetContentScaleFactor(webView.get(), 1.0); WKViewSetContentPosition(webView.get(), WKPointMake(0, 0)); out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0)); EXPECT_EQ(out.x, 0); EXPECT_EQ(out.y, 0); out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10)); EXPECT_EQ(out.x, 10); EXPECT_EQ(out.y, 10); WKViewSetContentPosition(webView.get(), WKPointMake(20, 20)); out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0)); EXPECT_EQ(out.x, 20); EXPECT_EQ(out.y, 20); out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10)); EXPECT_EQ(out.x, 30); EXPECT_EQ(out.y, 30); // At scale 2.0 the viewport distance values will be half // the ones seem in the contents. WKViewSetContentScaleFactor(webView.get(), 2.0); WKViewSetContentPosition(webView.get(), WKPointMake(0, 0)); out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0)); EXPECT_EQ(out.x, 0); EXPECT_EQ(out.y, 0); out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10)); EXPECT_EQ(out.x, 5); EXPECT_EQ(out.y, 5); WKViewSetContentPosition(webView.get(), WKPointMake(20, 20)); out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0)); EXPECT_EQ(out.x, 20); EXPECT_EQ(out.y, 20); out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10)); EXPECT_EQ(out.x, 25); EXPECT_EQ(out.y, 25); // At scale 0.5 the viewport distance values will be twice // the ones seem in the contents. WKViewSetContentScaleFactor(webView.get(), 0.5); WKViewSetContentPosition(webView.get(), WKPointMake(0, 0)); out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0)); EXPECT_EQ(out.x, 0); EXPECT_EQ(out.y, 0); out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10)); EXPECT_EQ(out.x, 20); EXPECT_EQ(out.y, 20); WKViewSetContentPosition(webView.get(), WKPointMake(20, 20)); out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0)); EXPECT_EQ(out.x, 20); EXPECT_EQ(out.y, 20); out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10)); EXPECT_EQ(out.x, 40); EXPECT_EQ(out.y, 40); // Let's add translation to the viewport. const int delta = 10; WKViewSetUserViewportTranslation(webView.get(), delta, delta); WKViewSetContentPosition(webView.get(), WKPointMake(0, 0)); out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0)); EXPECT_EQ(out.x, 0 - delta / 0.5); EXPECT_EQ(out.y, 0 - delta / 0.5); out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10)); EXPECT_EQ(out.x, 20 - delta / 0.5); EXPECT_EQ(out.y, 20 - delta / 0.5); WKViewSetContentPosition(webView.get(), WKPointMake(20, 20)); out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0)); EXPECT_EQ(out.x, 20 - delta / 0.5); EXPECT_EQ(out.y, 20 - delta / 0.5); out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10)); EXPECT_EQ(out.x, 40 - delta / 0.5); EXPECT_EQ(out.y, 40 - delta / 0.5); }
MiniBrowser::MiniBrowser(GMainLoop* mainLoop, Mode mode, int width, int height, int viewportHorizontalDisplacement, int viewportVerticalDisplacement) : m_context(AdoptWK, WKContextCreate()) , m_pageGroup(AdoptWK, (WKPageGroupCreateWithIdentifier(WKStringCreateWithUTF8CString("MiniBrowser")))) , m_window(new LinuxWindow(this, width, height)) , m_view(0) , m_mainLoop(mainLoop) , m_lastClickTime(0) , m_lastClickX(0) , m_lastClickY(0) , m_lastClickButton(kWKEventMouseButtonNoButton) , m_clickCount(0) , m_touchMocker(0) , m_mode(mode) , m_displayUpdateScheduled(false) , m_gestureRecognizer(GestureRecognizer(this)) , m_postponeTextInputUpdates(true) , m_shouldFocusEditableArea(false) , m_shouldRestoreViewportWhenLosingFocus(false) , m_pageHandlesTouchEvents(false) , m_viewportMinScale(0.25) , m_viewportMaxScale(5) , m_viewportUserScalable(true) , m_viewportInitScale(1) { g_main_loop_ref(m_mainLoop); WKPreferencesRef preferences = WKPageGroupGetPreferences(m_pageGroup.get()); WKPreferencesSetAcceleratedCompositingEnabled(preferences, true); WKPreferencesSetFrameFlatteningEnabled(preferences, true); WKPreferencesSetDeveloperExtrasEnabled(preferences, true); m_view = NIXViewCreate(m_context.get(), m_pageGroup.get()); NIXViewClient viewClient; memset(&viewClient, 0, sizeof(NIXViewClient)); viewClient.version = kNIXViewClientCurrentVersion; viewClient.clientInfo = this; viewClient.viewNeedsDisplay = MiniBrowser::viewNeedsDisplay; viewClient.webProcessCrashed = MiniBrowser::webProcessCrashed; viewClient.webProcessRelaunched = MiniBrowser::webProcessRelaunched; viewClient.doneWithTouchEvent = MiniBrowser::doneWithTouchEvent; viewClient.doneWithGestureEvent = MiniBrowser::doneWithGestureEvent; viewClient.pageDidRequestScroll = MiniBrowser::pageDidRequestScroll; viewClient.didChangeContentsSize = MiniBrowser::didChangeContentsSize; viewClient.didChangeViewportAttributes = MiniBrowser::didChangeViewportAttributes; viewClient.didFindZoomableArea = MiniBrowser::didFindZoomableArea; viewClient.updateTextInputState = MiniBrowser::updateTextInputState; NIXViewSetViewClient(m_view, &viewClient); NIXViewInitialize(m_view); WKPageLoaderClient loaderClient; memset(&loaderClient, 0, sizeof(loaderClient)); loaderClient.version = kWKPageLoaderClientCurrentVersion; loaderClient.clientInfo = this; loaderClient.didStartProgress = MiniBrowser::didStartProgress; WKPageSetPageLoaderClient(pageRef(), &loaderClient); if (m_mode == MobileMode) WKPageSetUseFixedLayout(pageRef(), true); WKSize size = m_window->size(); m_viewRect = WKRectMake(viewportHorizontalDisplacement, viewportVerticalDisplacement, size.width - viewportHorizontalDisplacement, size.height - viewportVerticalDisplacement); NIXViewSetSize(m_view, m_viewRect.size); if (viewportHorizontalDisplacement || viewportVerticalDisplacement) { NIXMatrix transform = NIXMatrixMakeTranslation(viewportHorizontalDisplacement, viewportVerticalDisplacement); NIXViewSetUserViewportTransformation(m_view, &transform); } NIXViewSetFocused(m_view, true); NIXViewSetVisible(m_view, true); NIXViewSetActive(m_view, true); }