Beispiel #1
0
void ScrollingCoordinator::updateMainFrameScrollPosition(const IntPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
{
    ASSERT(isMainThread());

    if (!m_page)
        return;

    FrameView* frameView = m_page->mainFrame()->view();
    if (!frameView)
        return;

    bool oldProgrammaticScroll = frameView->inProgrammaticScroll();
    frameView->setInProgrammaticScroll(programmaticScroll);

    frameView->setConstrainsScrollingToContentEdge(false);
    frameView->notifyScrollPositionChanged(scrollPosition);
    frameView->setConstrainsScrollingToContentEdge(true);

    frameView->setInProgrammaticScroll(oldProgrammaticScroll);

#if USE(ACCELERATED_COMPOSITING)
    if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
        if (programmaticScroll || scrollingLayerPositionAction == SetScrollingLayerPosition)
            scrollLayer->setPosition(-frameView->scrollPosition());
        else {
            scrollLayer->syncPosition(-frameView->scrollPosition());
            LayoutRect viewportRect = frameView->visibleContentRect();
            viewportRect.setLocation(IntPoint(frameView->scrollOffsetForFixedPosition()));
            syncChildPositions(viewportRect);
        }
    }
#else
    UNUSED_PARAM(scrollingLayerPositionAction);
#endif
}
Beispiel #2
0
void ScrollingCoordinator::updateMainFrameScrollPosition(const IntPoint& scrollPosition, bool programmaticScroll)
{
    ASSERT(isMainThread());

    if (!m_page)
        return;

    FrameView* frameView = m_page->mainFrame()->view();
    if (!frameView)
        return;

    bool oldProgrammaticScroll = frameView->inProgrammaticScroll();
    frameView->setInProgrammaticScroll(programmaticScroll);

    frameView->setConstrainsScrollingToContentEdge(false);
    frameView->notifyScrollPositionChanged(scrollPosition);
    frameView->setConstrainsScrollingToContentEdge(true);

    frameView->setInProgrammaticScroll(oldProgrammaticScroll);

#if USE(ACCELERATED_COMPOSITING)
    if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
        if (programmaticScroll)
            scrollLayer->setPosition(-frameView->scrollPosition());
        else
            scrollLayer->syncPosition(-frameView->scrollPosition());
    }
#endif
}
void ScrollingCoordinator::updateMainFrameScrollPosition(const IntPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
{
    ASSERT(isMainThread());

    if (!m_page)
        return;

    FrameView* frameView = m_page->mainFrame().view();
    if (!frameView)
        return;

    bool oldProgrammaticScroll = frameView->inProgrammaticScroll();
    frameView->setInProgrammaticScroll(programmaticScroll);

    frameView->setConstrainsScrollingToContentEdge(false);
    frameView->notifyScrollPositionChanged(scrollPosition);
    frameView->setConstrainsScrollingToContentEdge(true);

    frameView->setInProgrammaticScroll(oldProgrammaticScroll);

#if USE(ACCELERATED_COMPOSITING)
    if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
        GraphicsLayer* counterScrollingLayer = counterScrollingLayerForFrameView(frameView);
        GraphicsLayer* headerLayer = headerLayerForFrameView(frameView);
        GraphicsLayer* footerLayer = footerLayerForFrameView(frameView);
        IntSize scrollOffsetForFixed = frameView->scrollOffsetForFixedPosition();

        if (programmaticScroll || scrollingLayerPositionAction == SetScrollingLayerPosition) {
            scrollLayer->setPosition(-frameView->scrollPosition());
            if (counterScrollingLayer)
                counterScrollingLayer->setPosition(IntPoint(scrollOffsetForFixed));
            if (headerLayer)
                headerLayer->setPosition(FloatPoint(scrollOffsetForFixed.width(), 0));
            if (footerLayer)
                footerLayer->setPosition(FloatPoint(scrollOffsetForFixed.width(), frameView->totalContentsSize().height() - frameView->footerHeight()));
        } else {
            scrollLayer->syncPosition(-frameView->scrollPosition());
            if (counterScrollingLayer)
                counterScrollingLayer->syncPosition(IntPoint(scrollOffsetForFixed));
            if (headerLayer)
                headerLayer->syncPosition(FloatPoint(scrollOffsetForFixed.width(), 0));
            if (footerLayer)
                footerLayer->syncPosition(FloatPoint(scrollOffsetForFixed.width(), frameView->totalContentsSize().height() - frameView->footerHeight()));

            LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
            syncChildPositions(viewportRect);
        }
    }
#else
    UNUSED_PARAM(scrollingLayerPositionAction);
#endif
}
Beispiel #4
0
void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
{
    ASSERT(isMainThread());

    if (!m_page)
        return;

    FrameView* frameView = m_page->mainFrame().view();
    if (!frameView)
        return;

    bool oldProgrammaticScroll = frameView->inProgrammaticScroll();
    frameView->setInProgrammaticScroll(programmaticScroll);

    frameView->setConstrainsScrollingToContentEdge(false);
    frameView->notifyScrollPositionChanged(roundedIntPoint(scrollPosition));
    frameView->setConstrainsScrollingToContentEdge(true);

    frameView->setInProgrammaticScroll(oldProgrammaticScroll);

    if (scrollingNodeID == frameView->scrollLayerID()) {
        if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
            GraphicsLayer* counterScrollingLayer = counterScrollingLayerForFrameView(frameView);
            GraphicsLayer* headerLayer = headerLayerForFrameView(frameView);
            GraphicsLayer* footerLayer = footerLayerForFrameView(frameView);
            IntSize scrollOffsetForFixed = frameView->scrollOffsetForFixedPosition();

            if (programmaticScroll || scrollingLayerPositionAction == SetScrollingLayerPosition) {
                scrollLayer->setPosition(-frameView->scrollPosition());
                if (counterScrollingLayer)
                    counterScrollingLayer->setPosition(IntPoint(scrollOffsetForFixed));
                if (headerLayer)
                    headerLayer->setPosition(FloatPoint(scrollOffsetForFixed.width(), 0));
                if (footerLayer)
                    footerLayer->setPosition(FloatPoint(scrollOffsetForFixed.width(), frameView->totalContentsSize().height() - frameView->footerHeight()));
            } else {
                scrollLayer->syncPosition(-frameView->scrollPosition());
                if (counterScrollingLayer)
                    counterScrollingLayer->syncPosition(IntPoint(scrollOffsetForFixed));
                if (headerLayer)
                    headerLayer->syncPosition(FloatPoint(scrollOffsetForFixed.width(), 0));
                if (footerLayer)
                    footerLayer->syncPosition(FloatPoint(scrollOffsetForFixed.width(), frameView->totalContentsSize().height() - frameView->footerHeight()));

                LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
                syncChildPositions(viewportRect);
            }
        }
    }
    // FIXME: handle non-main scrolling nodes.
}
void PaintLayerCompositor::frameViewDidScroll()
{
    FrameView* frameView = m_layoutView.frameView();
    IntPoint scrollPosition = frameView->scrollPosition();

    if (!m_scrollLayer)
        return;

    bool scrollingCoordinatorHandlesOffset = false;
    if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
        scrollingCoordinatorHandlesOffset = scrollingCoordinator->scrollableAreaScrollLayerDidChange(frameView);
    }

    // Scroll position = scroll minimum + scroll offset. Adjust the layer's
    // position to handle whatever the scroll coordinator isn't handling.
    // The minimum scroll position is non-zero for RTL pages with overflow.
    if (scrollingCoordinatorHandlesOffset)
        m_scrollLayer->setPosition(-frameView->minimumScrollPosition());
    else
        m_scrollLayer->setPosition(-scrollPosition);


    Platform::current()->histogramEnumeration("Renderer.AcceleratedFixedRootBackground",
        ScrolledMainFrameBucket,
        AcceleratedFixedRootBackgroundHistogramMax);
}
void ScrollingCoordinator::updateMainFrameScrollPositionAndScrollLayerPosition()
{
#if USE(ACCELERATED_COMPOSITING) && ENABLE(THREADED_SCROLLING)
    ASSERT(isMainThread());

    if (!m_page)
        return;

    FrameView* frameView = m_page->mainFrame()->view();
    if (!frameView)
        return;

    IntPoint scrollPosition = m_scrollingTree->mainFrameScrollPosition();

    // Make sure to update the main frame scroll position before changing the scroll layer position,
    // otherwise we'll introduce jittering on pages with slow repaint objects (like background-attachment: fixed).
    frameView->updateCompositingLayers();
    frameView->setConstrainsScrollingToContentEdge(false);
    frameView->notifyScrollPositionChanged(scrollPosition);
    frameView->setConstrainsScrollingToContentEdge(true);

    if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView))
        scrollLayer->setPosition(-frameView->scrollPosition());
#endif
}
void HistoryController::saveScrollPositionAndViewStateToItem(HistoryItem* item)
{
    FrameView* frameView = m_frame.view();
    if (!item || !frameView)
        return;

    if (m_frame.document()->inPageCache())
        item->setScrollPosition(frameView->cachedScrollPosition());
    else
        item->setScrollPosition(frameView->scrollPosition());

#if PLATFORM(IOS)
    item->setExposedContentRect(frameView->exposedContentRect());
    item->setUnobscuredContentRect(frameView->unobscuredContentRect());
#endif

    Page* page = m_frame.page();
    if (page && m_frame.isMainFrame()) {
        item->setPageScaleFactor(page->pageScaleFactor() / page->viewScaleFactor());
#if PLATFORM(IOS)
        item->setObscuredInset(page->obscuredInset());
#endif
    }

    // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client.
    m_frame.loader().client().saveViewStateToItem(*item);

    // Notify clients that the HistoryItem has changed.
    item->notifyChanged();
}
bool DevToolsEmulator::handleInputEvent(const WebInputEvent& inputEvent)
{
    Page* page = m_webViewImpl->page();
    if (!page)
        return false;

    // FIXME: This workaround is required for touch emulation on Mac, where
    // compositor-side pinch handling is not enabled. See http://crbug.com/138003.
    bool isPinch = inputEvent.type == WebInputEvent::GesturePinchBegin || inputEvent.type == WebInputEvent::GesturePinchUpdate || inputEvent.type == WebInputEvent::GesturePinchEnd;
    if (isPinch && m_touchEventEmulationEnabled) {
        FrameView* frameView = page->deprecatedLocalMainFrame()->view();
        PlatformGestureEventBuilder gestureEvent(frameView, static_cast<const WebGestureEvent&>(inputEvent));
        float pageScaleFactor = page->pageScaleFactor();
        if (gestureEvent.type() == PlatformEvent::GesturePinchBegin) {
            m_lastPinchAnchorCss = adoptPtr(new IntPoint(frameView->scrollPosition() + gestureEvent.position()));
            m_lastPinchAnchorDip = adoptPtr(new IntPoint(gestureEvent.position()));
            m_lastPinchAnchorDip->scale(pageScaleFactor, pageScaleFactor);
        }
        if (gestureEvent.type() == PlatformEvent::GesturePinchUpdate && m_lastPinchAnchorCss) {
            float newPageScaleFactor = pageScaleFactor * gestureEvent.scale();
            IntPoint anchorCss(*m_lastPinchAnchorDip.get());
            anchorCss.scale(1.f / newPageScaleFactor, 1.f / newPageScaleFactor);
            m_webViewImpl->setPageScaleFactor(newPageScaleFactor);
            m_webViewImpl->mainFrame()->setScrollOffset(toIntSize(*m_lastPinchAnchorCss.get() - toIntSize(anchorCss)));
        }
        if (gestureEvent.type() == PlatformEvent::GesturePinchEnd) {
            m_lastPinchAnchorCss.clear();
            m_lastPinchAnchorDip.clear();
        }
        return true;
    }

    return false;
}
Beispiel #9
0
void Page::setPageScaleFactor(float scale, const IntPoint& origin)
{
    if (!mainFrame()->isLocalFrame())
        return;

    FrameView* view = deprecatedLocalMainFrame()->view();
    PinchViewport& viewport = frameHost().pinchViewport();

    if (scale != viewport.scale()) {
        viewport.setScale(scale);

        if (view && !settings().pinchVirtualViewportEnabled())
            view->setVisibleContentScaleFactor(scale);

        deprecatedLocalMainFrame()->deviceOrPageScaleFactorChanged();
        m_chrome->client().deviceOrPageScaleFactorChanged();

        // FIXME: In virtual-viewport pinch mode, scale doesn't change the fixed-pos viewport;
        // remove once it's the only pinch mode in town.
        if (view)
            view->viewportConstrainedVisibleContentSizeChanged(true, true);

        deprecatedLocalMainFrame()->loader().saveScrollState();
    }

    if (view && view->scrollPosition() != origin)
        view->notifyScrollPositionChanged(origin);
}
InRegionScrollableArea::InRegionScrollableArea(WebPagePrivate* webPage, RenderLayer* layer)
    : m_webPage(webPage)
    , m_layer(layer)
{
    ASSERT(webPage);
    ASSERT(layer);
    m_isNull = false;

    // FIXME: Add an ASSERT here as the 'layer' must be scrollable.

    RenderObject* layerRenderer = layer->renderer();
    ASSERT(layerRenderer);

    if (layerRenderer->isRenderView()) { // #document case

        FrameView* view = toRenderView(layerRenderer)->frameView();
        ASSERT(view);

        Frame* frame = view->frame();
        ASSERT_UNUSED(frame, frame);

        m_scrollPosition = m_webPage->mapToTransformed(view->scrollPosition());
        m_contentsSize = m_webPage->mapToTransformed(view->contentsSize());
        m_viewportSize = m_webPage->mapToTransformed(view->visibleContentRect(false /*includeScrollbars*/)).size();

        m_visibleWindowRect = m_webPage->mapToTransformed(m_webPage->getRecursiveVisibleWindowRect(view));
        IntRect transformedWindowRect = IntRect(IntPoint::zero(), m_webPage->transformedViewportSize());
        m_visibleWindowRect.intersect(transformedWindowRect);

        m_scrollsHorizontally = view->contentsWidth() > view->visibleWidth();
        m_scrollsVertically = view->contentsHeight() > view->visibleHeight();

        m_overscrollLimitFactor = 0.0; // FIXME eventually support overscroll
    } else { // RenderBox-based elements case (scrollable boxes (div's, p's, textarea's, etc)).

        RenderBox* box = m_layer->renderBox();
        ASSERT(box);
        ASSERT(box->canBeScrolledAndHasScrollableArea());

        ScrollableArea* scrollableArea = static_cast<ScrollableArea*>(m_layer);
        m_scrollPosition = m_webPage->mapToTransformed(scrollableArea->scrollPosition());
        m_contentsSize = m_webPage->mapToTransformed(scrollableArea->contentsSize());
        m_viewportSize = m_webPage->mapToTransformed(scrollableArea->visibleContentRect(false /*includeScrollbars*/)).size();

        m_visibleWindowRect = m_layer->renderer()->absoluteClippedOverflowRect();
        m_visibleWindowRect = m_layer->renderer()->frame()->view()->contentsToWindow(m_visibleWindowRect);
        IntRect visibleFrameWindowRect = m_webPage->getRecursiveVisibleWindowRect(m_layer->renderer()->frame()->view());
        m_visibleWindowRect.intersect(visibleFrameWindowRect);
        m_visibleWindowRect = m_webPage->mapToTransformed(m_visibleWindowRect);
        IntRect transformedWindowRect = IntRect(IntPoint::zero(), m_webPage->transformedViewportSize());
        m_visibleWindowRect.intersect(transformedWindowRect);

        m_scrollsHorizontally = box->scrollWidth() != box->clientWidth() && box->scrollsOverflowX();
        m_scrollsVertically = box->scrollHeight() != box->clientHeight() && box->scrollsOverflowY();

        m_overscrollLimitFactor = 0.0; // FIXME eventually support overscroll
    }
}
Beispiel #11
0
bool WebDevToolsAgentImpl::handleInputEvent(WebCore::Page* page, const WebInputEvent& inputEvent)
{
    if (!m_attached && !m_generatingEvent)
        return false;

    // FIXME: This workaround is required for touch emulation on Mac, where
    // compositor-side pinch handling is not enabled. See http://crbug.com/138003.
    bool isPinch = inputEvent.type == WebInputEvent::GesturePinchBegin || inputEvent.type == WebInputEvent::GesturePinchUpdate || inputEvent.type == WebInputEvent::GesturePinchEnd;
    if (isPinch && m_touchEventEmulationEnabled && m_emulateViewportEnabled) {
        FrameView* frameView = page->mainFrame()->view();
        PlatformGestureEventBuilder gestureEvent(frameView, *static_cast<const WebGestureEvent*>(&inputEvent));
        float pageScaleFactor = page->pageScaleFactor();
        if (gestureEvent.type() == PlatformEvent::GesturePinchBegin) {
            m_lastPinchAnchorCss = adoptPtr(new WebCore::IntPoint(frameView->scrollPosition() + gestureEvent.position()));
            m_lastPinchAnchorDip = adoptPtr(new WebCore::IntPoint(gestureEvent.position()));
            m_lastPinchAnchorDip->scale(pageScaleFactor, pageScaleFactor);
        }
        if (gestureEvent.type() == PlatformEvent::GesturePinchUpdate && m_lastPinchAnchorCss) {
            float newPageScaleFactor = pageScaleFactor * gestureEvent.scale();
            WebCore::IntPoint anchorCss(*m_lastPinchAnchorDip.get());
            anchorCss.scale(1.f / newPageScaleFactor, 1.f / newPageScaleFactor);
            m_webViewImpl->setPageScaleFactor(newPageScaleFactor);
            m_webViewImpl->setMainFrameScrollOffset(*m_lastPinchAnchorCss.get() - toIntSize(anchorCss));
        }
        if (gestureEvent.type() == PlatformEvent::GesturePinchEnd) {
            m_lastPinchAnchorCss.clear();
            m_lastPinchAnchorDip.clear();
        }
        return true;
    }

    InspectorController* ic = inspectorController();
    if (!ic)
        return false;

    if (WebInputEvent::isGestureEventType(inputEvent.type) && inputEvent.type == WebInputEvent::GestureTap) {
        // Only let GestureTab in (we only need it and we know PlatformGestureEventBuilder supports it).
        PlatformGestureEvent gestureEvent = PlatformGestureEventBuilder(page->mainFrame()->view(), *static_cast<const WebGestureEvent*>(&inputEvent));
        return ic->handleGestureEvent(page->mainFrame(), gestureEvent);
    }
    if (WebInputEvent::isMouseEventType(inputEvent.type) && inputEvent.type != WebInputEvent::MouseEnter) {
        // PlatformMouseEventBuilder does not work with MouseEnter type, so we filter it out manually.
        PlatformMouseEvent mouseEvent = PlatformMouseEventBuilder(page->mainFrame()->view(), *static_cast<const WebMouseEvent*>(&inputEvent));
        return ic->handleMouseEvent(page->mainFrame(), mouseEvent);
    }
    if (WebInputEvent::isTouchEventType(inputEvent.type)) {
        PlatformTouchEvent touchEvent = PlatformTouchEventBuilder(page->mainFrame()->view(), *static_cast<const WebTouchEvent*>(&inputEvent));
        return ic->handleTouchEvent(page->mainFrame(), touchEvent);
    }
    if (WebInputEvent::isKeyboardEventType(inputEvent.type)) {
        PlatformKeyboardEvent keyboardEvent = PlatformKeyboardEventBuilder(*static_cast<const WebKeyboardEvent*>(&inputEvent));
        return ic->handleKeyboardEvent(page->mainFrame(), keyboardEvent);
    }
    return false;
}
Beispiel #12
0
IntSize WebFrame::scrollOffset() const
{
    if (!m_coreFrame)
        return IntSize();
    
    FrameView* view = m_coreFrame->view();
    if (!view)
        return IntSize();

    return toIntSize(view->scrollPosition());
}
Beispiel #13
0
void Page::setPageScaleFactor(float scale, const IntPoint& origin)
{
    Document* document = mainFrame()->document();
    FrameView* view = document->view();

    if (scale == m_pageScaleFactor) {
        if (view && (view->scrollPosition() != origin || view->delegatesScrolling())) {
            if (!m_settings->applyPageScaleFactorInCompositor())
                document->updateLayoutIgnorePendingStylesheets();
            view->setScrollPosition(origin);
        }
        return;
    }

    m_pageScaleFactor = scale;

    if (!m_settings->applyPageScaleFactorInCompositor()) {
        if (document->renderer())
            document->renderer()->setNeedsLayout(true);

        document->recalcStyle(Style::Force);

        // Transform change on RenderView doesn't trigger repaint on non-composited contents.
        mainFrame()->view()->invalidateRect(IntRect(LayoutRect::infiniteRect()));
    }

#if USE(ACCELERATED_COMPOSITING)
    mainFrame()->deviceOrPageScaleFactorChanged();
#endif

    if (view && view->fixedElementsLayoutRelativeToFrame())
        view->setViewportConstrainedObjectsNeedLayout();

    if (view && view->scrollPosition() != origin) {
        if (!m_settings->applyPageScaleFactorInCompositor() && document->renderer() && document->renderer()->needsLayout() && view->didFirstLayout())
            view->layout();
        view->setScrollPosition(origin);
    }
}
void AsyncScrollingCoordinator::updateMainFrameScrollLayerPosition()
{
    ASSERT(isMainThread());

    if (!m_page)
        return;

    FrameView* frameView = m_page->mainFrame().view();
    if (!frameView)
        return;

    if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(*frameView))
        scrollLayer->setPosition(-frameView->scrollPosition());
}
void PluginViewPrivate::setVisibleRects(const NPRect rects[], int32_t count)
{
    m_keepVisibleRect = IntRect();

    if (!m_view->parent() || !count)
        return;

    for (int i = 0; i < count; i++) {
        IntRect addRect = IntRect(rects[i].left, rects[i].top, rects[i].right - rects[i].left, rects[i].bottom - rects[i].top);
        m_keepVisibleRect.unite(addRect);
    }

    // Don't cause a possible scroll if the result is an empty rectangle.
    if (m_keepVisibleRect.isEmpty())
        return;

    // Adjust the rect to the parent window and then adjust for scrolling.
    m_keepVisibleRect = m_view->convertToContainingWindow(m_keepVisibleRect);
    FrameView* frameView = static_cast<FrameView*>(m_view->parent());
    m_keepVisibleRect.move(frameView->scrollPosition().x(), frameView->scrollPosition().y());

    frameView->hostWindow()->platformPageClient()->ensureContentVisible();
}
PassRefPtr<WebImage> InjectedBundleRangeHandle::renderedImage(SnapshotOptions options)
{
    Document& ownerDocument = m_range->ownerDocument();
    Frame* frame = ownerDocument.frame();
    if (!frame)
        return nullptr;

    FrameView* frameView = frame->view();
    if (!frameView)
        return nullptr;

    Ref<Frame> protector(*frame);

    VisibleSelection oldSelection = frame->selection().selection();
    frame->selection().setSelection(VisibleSelection(*m_range));

    float scaleFactor = (options & SnapshotOptionsExcludeDeviceScaleFactor) ? 1 : frame->page()->deviceScaleFactor();
    IntRect paintRect = enclosingIntRect(m_range->absoluteBoundingRect());
    IntSize backingStoreSize = paintRect.size();
    backingStoreSize.scale(scaleFactor);

    RefPtr<ShareableBitmap> backingStore = ShareableBitmap::createShareable(backingStoreSize, ShareableBitmap::SupportsAlpha);
    if (!backingStore)
        return nullptr;

    auto graphicsContext = backingStore->createGraphicsContext();
    graphicsContext->scale(scaleFactor);

    paintRect.move(frameView->frameRect().x(), frameView->frameRect().y());
    paintRect.moveBy(-frameView->scrollPosition());

    graphicsContext->translate(-paintRect.x(), -paintRect.y());

    PaintBehavior oldPaintBehavior = frameView->paintBehavior();
    PaintBehavior paintBehavior = oldPaintBehavior | PaintBehaviorSelectionOnly | PaintBehaviorFlattenCompositingLayers;
    if (options & SnapshotOptionsForceBlackText)
        paintBehavior |= PaintBehaviorForceBlackText;
    if (options & SnapshotOptionsForceWhiteText)
        paintBehavior |= PaintBehaviorForceWhiteText;

    frameView->setPaintBehavior(paintBehavior);
    ownerDocument.updateLayout();

    frameView->paint(*graphicsContext, paintRect);
    frameView->setPaintBehavior(oldPaintBehavior);

    frame->selection().setSelection(oldSelection);

    return WebImage::create(backingStore);
}
Beispiel #17
0
void Page::setPageScaleFactor(float scale, const IntPoint& origin)
{
    FrameView* view = mainFrame()->view();

    if (scale == m_pageScaleFactor) {
        if (view && view->scrollPosition() != origin)
            view->setScrollPosition(origin);
        return;
    }

    m_pageScaleFactor = scale;

    if (view)
        view->setVisibleContentScaleFactor(scale);

    mainFrame()->deviceOrPageScaleFactorChanged();

    if (view)
        view->setViewportConstrainedObjectsNeedLayout();

    if (view && view->scrollPosition() != origin)
        view->setScrollPosition(origin);
}
Beispiel #18
0
void ScrollingCoordinator::updateMainFrameScrollPositionAndScrollLayerPosition(const IntPoint& scrollPosition)
{
    FrameView* frameView = m_page->mainFrame()->view();

    RenderView* renderView = m_page->mainFrame()->contentRenderer();
    if (!renderView)
        return;

    GraphicsLayer* scrollLayer = renderView->compositor()->scrollLayer();
    if (!scrollLayer)
        return;

    frameView->updateCompositingLayers();
    frameView->setConstrainsScrollingToContentEdge(false);
    frameView->notifyScrollPositionChanged(scrollPosition);
    frameView->setConstrainsScrollingToContentEdge(true);

    scrollLayer->setPosition(-frameView->scrollPosition());
}
Beispiel #19
0
void PinchViewport::scrollIntoView(const FloatRect& rect)
{
    if (!mainFrame() || !mainFrame()->view())
        return;

    FrameView* view = mainFrame()->view();

    float centeringOffsetX = (visibleRect().width() - rect.width()) / 2;
    float centeringOffsetY = (visibleRect().height() - rect.height()) / 2;

    FloatPoint targetOffset(
        rect.x() - centeringOffsetX - visibleRect().x(),
        rect.y() - centeringOffsetY - visibleRect().y());

    view->setScrollPosition(flooredIntPoint(targetOffset));

    FloatPoint remainder = FloatPoint(targetOffset - view->scrollPosition());
    move(remainder);
}
static bool pointWithScrollAndZoomIfPossible(const Document& document, IntPoint& point)
{
    LocalFrame* frame = document.frame();
    if (!frame)
        return false;
    FrameView* frameView = frame->view();
    if (!frameView)
        return false;

    FloatPoint pointInDocument(point);
    pointInDocument.scale(frame->pageZoomFactor(), frame->pageZoomFactor());
    pointInDocument.moveBy(frameView->scrollPosition());
    IntPoint roundedPointInDocument = roundedIntPoint(pointInDocument);

    if (!frameView->visibleContentRect().contains(roundedPointInDocument))
        return false;

    point = roundedPointInDocument;
    return true;
}
Beispiel #21
0
void Page::setPageScaleFactor(float scale, const IntPoint& origin)
{
    FrameView* view = mainFrame()->view();

    if (scale != m_pageScaleFactor) {
        m_pageScaleFactor = scale;

        if (view)
            view->setVisibleContentScaleFactor(scale);

        mainFrame()->deviceOrPageScaleFactorChanged();
        m_chrome->client().deviceOrPageScaleFactorChanged();

        if (view)
            view->viewportConstrainedVisibleContentSizeChanged(true, true);
    }

    if (view && view->scrollPosition() != origin)
        view->notifyScrollPositionChanged(origin);
}
Beispiel #22
0
void Page::setPageScaleFactor(float scale, const IntPoint& origin)
{
    FrameView* view = mainFrame()->view();

    bool oldProgrammaticScroll = view->inProgrammaticScroll();
    view->setInProgrammaticScroll(false);

    if (scale != m_pageScaleFactor) {
        m_pageScaleFactor = scale;

        if (view)
            view->setVisibleContentScaleFactor(scale);

        mainFrame()->deviceOrPageScaleFactorChanged();

        if (view)
            view->setViewportConstrainedObjectsNeedLayout();
    }

    if (view && view->scrollPosition() != origin)
        view->notifyScrollPositionChanged(origin);

    view->setInProgrammaticScroll(oldProgrammaticScroll);
}
InRegionScrollableArea::InRegionScrollableArea(WebPagePrivate* webPage, RenderLayer* layer)
    : m_webPage(webPage)
    , m_layer(layer)
    , m_document(0)
    , m_hasWindowVisibleRectCalculated(false)
{
    ASSERT(webPage);
    ASSERT(layer);
    m_isNull = false;

    // Add a pointer to the enclosing document as the pointer to layer or node along the way may become invalid.
    if (m_layer->enclosingElement())
        m_document = m_layer->enclosingElement()->document();

    // FIXME: Add an ASSERT here as the 'layer' must be scrollable.

    RenderObject* layerRenderer = layer->renderer();
    ASSERT(layerRenderer);

    if (layerRenderer->isRenderView()) { // #document case

        RenderView* renderView = toRenderView(layerRenderer);
        ASSERT(renderView);

        FrameView* view = toRenderView(layerRenderer)->frameView();
        ASSERT(view);

        Frame* frame = view->frame();
        ASSERT_UNUSED(frame, frame);

        const Platform::ViewportAccessor* viewportAccessor = m_webPage->m_webkitThreadViewportAccessor;
        m_scrollPosition = viewportAccessor->roundToPixelFromDocumentContents(WebCore::FloatPoint(view->scrollPosition()));
        m_contentsSize = viewportAccessor->roundToPixelFromDocumentContents(Platform::FloatRect(Platform::FloatPoint::zero(), WebCore::FloatSize(view->contentsSize()))).size();
        m_viewportSize = viewportAccessor->roundToPixelFromDocumentContents(WebCore::FloatRect(view->visibleContentRect(ScrollableArea::ExcludeScrollbars))).size();
        m_documentViewportRect = view->frameRect();

        m_scrollsHorizontally = view->contentsWidth() > view->visibleWidth();
        m_scrollsVertically = view->contentsHeight() > view->visibleHeight();

        m_supportsCompositedScrolling = true;

        m_scrollTarget = InnerFrame;

        ASSERT(!m_cachedNonCompositedScrollableNode);

        m_camouflagedCompositedScrollableLayer = reinterpret_cast<unsigned>(renderView->compositor()->scrollLayer()->platformLayer());
        m_cachedCompositedScrollableLayer = renderView->compositor()->scrollLayer()->platformLayer();

    } else { // RenderBox-based elements case (scrollable boxes (div's, p's, textarea's, etc)).

        RenderBox* box = m_layer->renderBox();
        ASSERT(box);
        ASSERT(InRegionScrollerPrivate::canScrollRenderBox(box));

        const Platform::ViewportAccessor* viewportAccessor = m_webPage->m_webkitThreadViewportAccessor;
        ScrollableArea* scrollableArea = static_cast<ScrollableArea*>(m_layer);

        m_scrollPosition = viewportAccessor->roundToPixelFromDocumentContents(WebCore::FloatPoint(scrollableArea->scrollPosition()));
        m_contentsSize = viewportAccessor->roundToPixelFromDocumentContents(Platform::FloatRect(Platform::FloatPoint::zero(), WebCore::FloatSize(scrollableArea->contentsSize()))).size();
        m_viewportSize = viewportAccessor->roundToPixelFromDocumentContents(WebCore::FloatRect(scrollableArea->visibleContentRect(ScrollableArea::ExcludeScrollbars))).size();
        m_documentViewportRect = enclosingIntRect(box->absoluteClippedOverflowRect());

        m_scrollsHorizontally = box->scrollWidth() != box->clientWidth();
        m_scrollsVertically = box->scrollHeight() != box->clientHeight();

        // Check the overflow if its not an input field because overflow can be set to hidden etc. by the content.
        if (!DOMSupport::isShadowHostTextInputElement(box->node())) {
            m_scrollsHorizontally = m_scrollsHorizontally && box->scrollsOverflowX();
            m_scrollsVertically = m_scrollsVertically && box->scrollsOverflowY();
        }

        m_scrollTarget = BlockElement;

        // Both caches below are self-exclusive.
        if (m_layer->usesCompositedScrolling()) {
            m_forceContentToBeHorizontallyScrollable = m_scrollsHorizontally;
            m_forceContentToBeVerticallyScrollable = m_scrollsVertically;
            // Force content to be scrollable even if it doesn't need to scroll in either direction.
            if (!m_scrollsHorizontally && !m_scrollsVertically) {
                if (box->scrollsOverflowY())
                    m_forceContentToBeVerticallyScrollable = true;
                else if (box->scrollsOverflowX()) // If it's already forced scrollable vertically, don't force it to scroll horizontally
                    m_forceContentToBeHorizontallyScrollable = true;
            }
            m_supportsCompositedScrolling = true;
            ASSERT(m_layer->backing()->hasScrollingLayer());
            m_camouflagedCompositedScrollableLayer = reinterpret_cast<unsigned>(m_layer->backing()->scrollingContentsLayer()->platformLayer());
            m_cachedCompositedScrollableLayer = m_layer->backing()->scrollingContentsLayer()->platformLayer();
            ASSERT(!m_cachedNonCompositedScrollableNode);
        } else {
            m_camouflagedCompositedScrollableLayer = reinterpret_cast<unsigned>(m_layer->enclosingElement());
            m_cachedNonCompositedScrollableNode = m_layer->enclosingElement();
            ASSERT(!m_cachedCompositedScrollableLayer);
        }
    }
}
void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
{
    ASSERT(isMainThread());

    if (!m_page)
        return;

    FrameView* frameView = m_page->mainFrame().view();
    if (!frameView)
        return;

    // Main frame.
    if (scrollingNodeID == frameView->scrollLayerID()) {
        bool oldProgrammaticScroll = frameView->inProgrammaticScroll();
        frameView->setInProgrammaticScroll(programmaticScroll);

        frameView->setConstrainsScrollingToContentEdge(false);
        frameView->notifyScrollPositionChanged(roundedIntPoint(scrollPosition));
        frameView->setConstrainsScrollingToContentEdge(true);

        frameView->setInProgrammaticScroll(oldProgrammaticScroll);

        if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
            GraphicsLayer* counterScrollingLayer = counterScrollingLayerForFrameView(frameView);
            GraphicsLayer* insetClipLayer = insetClipLayerForFrameView(frameView);
            GraphicsLayer* contentShadowLayer = contentShadowLayerForFrameView(frameView);
            GraphicsLayer* scrolledContentsLayer = rootContentLayerForFrameView(frameView);
            GraphicsLayer* headerLayer = headerLayerForFrameView(frameView);
            GraphicsLayer* footerLayer = footerLayerForFrameView(frameView);
            LayoutSize scrollOffsetForFixed = frameView->scrollOffsetForFixedPosition();

            float topContentInset = frameView->topContentInset();
            FloatPoint positionForInsetClipLayer = FloatPoint(0, FrameView::yPositionForInsetClipLayer(scrollPosition, topContentInset));
            FloatPoint positionForContentsLayer = FloatPoint(scrolledContentsLayer->position().x(),
                FrameView::yPositionForRootContentLayer(scrollPosition, topContentInset, frameView->headerHeight()));
            FloatPoint positionForHeaderLayer = FloatPoint(scrollOffsetForFixed.width(), FrameView::yPositionForHeaderLayer(scrollPosition, topContentInset));
            FloatPoint positionForFooterLayer = FloatPoint(scrollOffsetForFixed.width(),
                FrameView::yPositionForFooterLayer(scrollPosition, topContentInset, frameView->totalContentsSize().height(), frameView->footerHeight()));

            if (programmaticScroll || scrollingLayerPositionAction == SetScrollingLayerPosition) {
                scrollLayer->setPosition(-frameView->scrollPosition());
                if (counterScrollingLayer)
                    counterScrollingLayer->setPosition(toLayoutPoint(scrollOffsetForFixed));
                if (insetClipLayer)
                    insetClipLayer->setPosition(positionForInsetClipLayer);
                if (contentShadowLayer)
                    contentShadowLayer->setPosition(positionForContentsLayer);
                if (scrolledContentsLayer)
                    scrolledContentsLayer->setPosition(positionForContentsLayer);
                if (headerLayer)
                    headerLayer->setPosition(positionForHeaderLayer);
                if (footerLayer)
                    footerLayer->setPosition(positionForFooterLayer);
            } else {
                scrollLayer->syncPosition(-frameView->scrollPosition());
                if (counterScrollingLayer)
                    counterScrollingLayer->syncPosition(toLayoutPoint(scrollOffsetForFixed));
                if (insetClipLayer)
                    insetClipLayer->syncPosition(positionForInsetClipLayer);
                if (contentShadowLayer)
                    contentShadowLayer->syncPosition(positionForContentsLayer);
                if (scrolledContentsLayer)
                    scrolledContentsLayer->syncPosition(positionForContentsLayer);
                if (headerLayer)
                    headerLayer->syncPosition(positionForHeaderLayer);
                if (footerLayer)
                    footerLayer->syncPosition(positionForFooterLayer);

                LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
                syncChildPositions(viewportRect);
            }
        }

        return;
    }

    // Overflow-scroll area.
    if (ScrollableArea* scrollableArea = frameView->scrollableAreaForScrollLayerID(scrollingNodeID)) {
        scrollableArea->setIsUserScroll(scrollingLayerPositionAction == SyncScrollingLayerPosition);
        scrollableArea->scrollToOffsetWithoutAnimation(scrollPosition);
        scrollableArea->setIsUserScroll(false);
    }
}
InRegionScrollableArea::InRegionScrollableArea(WebPagePrivate* webPage, RenderLayer* layer)
    : m_webPage(webPage)
    , m_layer(layer)
    , m_document(0)
    , m_hasWindowVisibleRectCalculated(false)
{
    ASSERT(webPage);
    ASSERT(layer);
    m_isNull = false;

    // Add a pointer to the enclosing document as the pointer to layer or node along the way may become invalid.
    if (m_layer->enclosingElement())
        m_document = m_layer->enclosingElement()->document();

    // FIXME: Add an ASSERT here as the 'layer' must be scrollable.

    RenderObject* layerRenderer = layer->renderer();
    ASSERT(layerRenderer);

    if (layerRenderer->isRenderView()) { // #document case

        RenderView* renderView = toRenderView(layerRenderer);
        ASSERT(renderView);

        FrameView* view = toRenderView(layerRenderer)->frameView();
        ASSERT(view);

        Frame* frame = view->frame();
        ASSERT_UNUSED(frame, frame);

        m_scrollPosition = m_webPage->mapToTransformed(view->scrollPosition());
        m_contentsSize = m_webPage->mapToTransformed(view->contentsSize());
        m_viewportSize = m_webPage->mapToTransformed(view->visibleContentRect(ScrollableArea::ExcludeScrollbars)).size();
        m_documentViewportRect = view->frameRect();

        m_scrollsHorizontally = view->contentsWidth() > view->visibleWidth();
        m_scrollsVertically = view->contentsHeight() > view->visibleHeight();

        m_supportsCompositedScrolling = true;

        m_scrollTarget = InnerFrame;

        ASSERT(!m_cachedNonCompositedScrollableNode);

        m_camouflagedCompositedScrollableLayer = reinterpret_cast<unsigned>(renderView->compositor()->scrollLayer()->platformLayer());
        m_cachedCompositedScrollableLayer = renderView->compositor()->scrollLayer()->platformLayer();

    } else { // RenderBox-based elements case (scrollable boxes (div's, p's, textarea's, etc)).

        RenderBox* box = m_layer->renderBox();
        ASSERT(box);
        ASSERT(InRegionScrollerPrivate::canScrollRenderBox(box));

        ScrollableArea* scrollableArea = static_cast<ScrollableArea*>(m_layer);
        m_scrollPosition = m_webPage->mapToTransformed(scrollableArea->scrollPosition());
        m_contentsSize = m_webPage->mapToTransformed(scrollableArea->contentsSize());
        m_viewportSize = m_webPage->mapToTransformed(scrollableArea->visibleContentRect(ScrollableArea::ExcludeScrollbars)).size();
        m_documentViewportRect = enclosingIntRect(box->absoluteClippedOverflowRect());

        m_scrollsHorizontally = box->scrollWidth() != box->clientWidth();
        m_scrollsVertically = box->scrollHeight() != box->clientHeight();

        // Check the overflow if its not an input field because overflow can be set to hidden etc. by the content.
        if (!box->node() || !box->node()->rendererIsEditable()) {
            m_scrollsHorizontally = m_scrollsHorizontally && box->scrollsOverflowX();
            m_scrollsVertically = m_scrollsVertically && box->scrollsOverflowY();
        }

        m_scrollTarget = BlockElement;

        // Both caches below are self-exclusive.
        if (m_layer->usesCompositedScrolling()) {
            m_forceContentToBeVerticallyScrollable = true;
            m_supportsCompositedScrolling = true;
            ASSERT(m_layer->backing()->hasScrollingLayer());
            m_camouflagedCompositedScrollableLayer = reinterpret_cast<unsigned>(m_layer->backing()->scrollingContentsLayer()->platformLayer());
            m_cachedCompositedScrollableLayer = m_layer->backing()->scrollingContentsLayer()->platformLayer();
            ASSERT(!m_cachedNonCompositedScrollableNode);
        } else {
            m_camouflagedCompositedScrollableLayer = reinterpret_cast<unsigned>(m_layer->enclosingElement());
            m_cachedNonCompositedScrollableNode = m_layer->enclosingElement();
            ASSERT(!m_cachedCompositedScrollableLayer);
        }
    }
}