void HTMLBodyElement::setScrollTop(int scrollTop)
{
    Document& document = this->document();
    document.updateLayoutIgnorePendingStylesheets();

    if (RuntimeEnabledFeatures::scrollTopLeftInteropEnabled()) {
        RenderBox* render = renderBox();
        if (!render)
            return;
        if (render->hasOverflowClip()) {
            // FIXME: Investigate how are other browsers casting to int (rounding, ceiling, ...).
            render->setScrollTop(static_cast<int>(scrollTop * render->style()->effectiveZoom()));
            return;
        }
        if (!document.inQuirksMode())
            return;
    }

    LocalFrame* frame = document.frame();
    if (!frame)
        return;
    FrameView* view = frame->view();
    if (!view)
        return;
    view->setScrollPosition(IntPoint(view->scrollX(), static_cast<int>(scrollTop * frame->pageZoomFactor())));
}
void HTMLBodyElement::setScrollTop(int scrollTop)
{
    FrameView* sview = ownerDocument()->view();
    if (sview) {
        // Update the document's layout
        document()->updateLayoutIgnorePendingStylesheets();
        sview->setScrollPosition(IntPoint(sview->scrollX(), static_cast<int>(scrollTop * sview->frame()->zoomFactor())));
    }        
}
Beispiel #3
0
void HTMLBodyElement::setScrollTop(int scrollTop)
{
    Document* document = this->document();
    document->updateLayoutIgnorePendingStylesheets();
    FrameView* view = document->view();
    if (!view)
        return;
    view->setScrollPosition(IntPoint(view->scrollX(), static_cast<int>(scrollTop * view->zoomFactor())));
}
/*
 There is a race condition between the layout and load completion that affects restoring the scroll position.
 We try to restore the scroll position at both the first layout and upon load completion.
 
 1) If first layout happens before the load completes, we want to restore the scroll position then so that the
 first time we draw the page is already scrolled to the right place, instead of starting at the top and later
 jumping down.  It is possible that the old scroll position is past the part of the doc laid out so far, in
 which case the restore silent fails and we will fix it in when we try to restore on doc completion.
 2) If the layout happens after the load completes, the attempt to restore at load completion time silently
 fails.  We then successfully restore it when the layout happens.
*/
void HistoryController::restoreScrollPositionAndViewState()
{
    if (!m_frame.loader().stateMachine().committedFirstRealDocumentLoad())
        return;

    ASSERT(m_currentItem);
    
    // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
    // One counterexample is <rdar://problem/4917290>
    // For now, to cover this issue in release builds, there is no technical harm to returning
    // early and from a user standpoint - as in the above radar - the previous page load failed 
    // so there *is* no scroll or view state to restore!
    if (!m_currentItem)
        return;

    FrameView* view = m_frame.view();

    // FIXME: There is some scrolling related work that needs to happen whenever a page goes into the
    // page cache and similar work that needs to occur when it comes out. This is where we do the work
    // that needs to happen when we exit, and the work that needs to happen when we enter is in
    // Document::setIsInPageCache(bool). It would be nice if there was more symmetry in these spots.
    // https://bugs.webkit.org/show_bug.cgi?id=98698
    if (view) {
        Page* page = m_frame.page();
        if (page && m_frame.isMainFrame()) {
            if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
                scrollingCoordinator->frameViewRootLayerDidChange(*view);
        }
    }

    // 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().restoreViewState();

#if !PLATFORM(IOS) && !PLATFORM(EFL)
    // Don't restore scroll point on iOS as FrameLoaderClient::restoreViewState() does that.
    if (view && !view->wasScrolledByUser()) {
        Page* page = m_frame.page();
        auto desiredScrollPosition = m_currentItem->scrollPosition();

        if (page && m_frame.isMainFrame() && m_currentItem->pageScaleFactor())
            page->setPageScaleFactor(m_currentItem->pageScaleFactor() * page->viewScaleFactor(), desiredScrollPosition);
        else
            view->setScrollPosition(desiredScrollPosition);

        // If the scroll position doesn't have to be clamped, consider it successfully restored.
        if (m_frame.isMainFrame()) {
            auto adjustedDesiredScrollPosition = view->adjustScrollPositionWithinRange(desiredScrollPosition);
            if (desiredScrollPosition == adjustedDesiredScrollPosition)
                m_frame.loader().client().didRestoreScrollPosition();
        }

    }
#endif
}
Beispiel #5
0
void HTMLBodyElement::setScrollTop(int scrollTop)
{
    document().updateLayoutIgnorePendingStylesheets();
    Frame* frame = document().frame();
    if (!frame)
        return;
    FrameView* view = frame->view();
    if (!view)
        return;
    view->setScrollPosition(IntPoint(view->scrollX(), static_cast<int>(scrollTop * frame->pageZoomFactor() * frame->frameScaleFactor())));
}
Beispiel #6
0
void HTMLBodyElement::setScrollLeft(int scrollLeft)
{
    Document* document = this->document();
    document->updateLayoutIgnorePendingStylesheets();
    Frame* frame = document->frame();
    if (!frame)
        return;
    FrameView* view = frame->view();
    if (!view)
        return;
    view->setScrollPosition(IntPoint(static_cast<int>(scrollLeft * frame->pageZoomFactor() * frame->pageScaleFactor()), view->scrollY()));
}
TEST_F(EventHandlerTest, dragSelectionAfterScroll)
{
    setHtmlInnerHTML("<style> body { margin: 0px; } .upper { width: 300px; height: 400px; }"
        ".lower { margin: 0px; width: 300px; height: 400px; } .line { display: block; width: 300px; height: 30px; } </style>"
        "<div class='upper'></div>"
        "<div class='lower'>"
        "<span class='line'>Line 1</span><span class='line'>Line 2</span><span class='line'>Line 3</span><span class='line'>Line 4</span><span class='line'>Line 5</span>"
        "<span class='line'>Line 6</span><span class='line'>Line 7</span><span class='line'>Line 8</span><span class='line'>Line 9</span><span class='line'>Line 10</span>"
        "</div>");

    FrameView* frameView = document().view();
    frameView->setScrollPosition(DoublePoint(0, 400), ProgrammaticScroll);

    PlatformMouseEvent mouseDownEvent(
        IntPoint(0, 0),
        IntPoint(100, 200),
        LeftButton,
        PlatformEvent::MousePressed,
        1,
        PlatformEvent::Modifiers::LeftButtonDown,
        WTF::monotonicallyIncreasingTime());
    document().frame()->eventHandler().handleMousePressEvent(mouseDownEvent);

    PlatformMouseEvent mouseMoveEvent(
        IntPoint(100, 50),
        IntPoint(200, 250),
        LeftButton,
        PlatformEvent::MouseMoved,
        1,
        PlatformEvent::Modifiers::LeftButtonDown,
        WTF::monotonicallyIncreasingTime());
    document().frame()->eventHandler().handleMouseMoveEvent(mouseMoveEvent);

    page().autoscrollController().animate(WTF::monotonicallyIncreasingTime());
    page().animator().serviceScriptedAnimations(WTF::monotonicallyIncreasingTime());

    PlatformMouseEvent mouseUpEvent(
        IntPoint(100, 50),
        IntPoint(200, 250),
        LeftButton,
        PlatformEvent::MouseReleased,
        1,
        static_cast<PlatformEvent::Modifiers>(0),
        WTF::monotonicallyIncreasingTime());
    document().frame()->eventHandler().handleMouseReleaseEvent(mouseUpEvent);

    FrameSelection& selection = document().frame()->selection();
    ASSERT_TRUE(selection.isRange());
    Range* range = createRange(selection.selection().toNormalizedEphemeralRange());
    ASSERT_TRUE(range);
    EXPECT_EQ("Line 1\nLine 2", range->text());
}
Beispiel #8
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);
    }
}
Beispiel #9
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 #10
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);
}