Example #1
0
IntRect WebFrame::visibleContentBoundsExcludingScrollbars() const
{
    if (!m_coreFrame)
        return IntRect();
    
    FrameView* view = m_coreFrame->view();
    if (!view)
        return IntRect();
    
    IntRect contentRect = view->visibleContentRect(false);
    return IntRect(0, 0, contentRect.width(), contentRect.height());
}
Example #2
0
IntRect WebFrame::visibleContentBounds() const
{
    if (!m_coreFrame)
        return IntRect();
    
    FrameView* view = m_coreFrame->view();
    if (!view)
        return IntRect();
    
    IntRect contentRect = view->visibleContentRect(ScrollableArea::IncludeScrollbars);
    return IntRect(0, 0, contentRect.width(), contentRect.height());
}
Example #3
0
BalRectangle WebFrame::visibleContentRect()
{
    Frame* frame = core(this);
    if (!frame)
        return BalRectangle();

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

    return view->visibleContentRect(false);
}
Example #4
0
BalRectangle WebFrame::frameBounds()
{
    Frame* coreFrame = core(this);
    if (!coreFrame)
        return IntRect();

    FrameView* view = coreFrame->view();
    if (!view)
        return IntRect();

    FloatRect bounds = view->visibleContentRect();
    return IntRect(0, 0, (int)bounds.width(), (int)bounds.height());
}
void InspectorOverlay::update()
{
    if (!m_highlightNode && !m_highlightQuad && m_pausedInDebuggerMessage.isNull() && m_size.isEmpty()) {
        m_client->hideHighlight();
        return;
    }

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

    FrameView* overlayView = overlayPage()->mainFrame()->view();
    IntSize viewportSize = view->visibleContentRect().size();
    IntSize frameViewFullSize = view->visibleContentRect(ScrollableArea::IncludeScrollbars).size();
    IntSize size = m_size.isEmpty() ? frameViewFullSize : m_size;
    overlayPage()->setPageScaleFactor(m_page->pageScaleFactor(), IntPoint());
    size.scale(m_page->pageScaleFactor());
    overlayView->resize(size);

    // Clear canvas and paint things.
    reset(viewportSize, m_size.isEmpty() ? IntSize() : frameViewFullSize);

    // Include scrollbars to avoid masking them by the gutter.
    drawGutter();
    drawNodeHighlight();
    drawQuadHighlight();
    drawPausedInDebuggerMessage();

    // Position DOM elements.
    overlayPage()->mainFrame()->document()->recalcStyle(Node::Force);
    if (overlayView->needsLayout())
        overlayView->layout();

    // Kick paint.
    m_client->highlight();
}
Example #6
0
InRegionScrollableArea::InRegionScrollableArea(WebPagePrivate* webPage, RenderLayer* layer)
    : m_webPage(webPage)
    , m_layer(layer)
    , m_hasWindowVisibleRectCalculated(false)
{
    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_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_scrollsHorizontally = box->scrollWidth() != box->clientWidth() && box->scrollsOverflowX();
        m_scrollsVertically = box->scrollHeight() != box->clientHeight() && box->scrollsOverflowY();

        m_overscrollLimitFactor = 0.0; // FIXME eventually support overscroll
    }
}
// Checks if |node| is offscreen the visible area (viewport) of its container
// document. In case it is, one can scroll in direction or take any different
// desired action later on.
bool hasOffscreenRect(Node* node, FocusDirection direction)
{
    // Get the FrameView in which |node| is (which means the current viewport if |node|
    // is not in an inner document), so we can check if its content rect is visible
    // before we actually move the focus to it.
    FrameView* frameView = node->document()->view();
    if (!frameView)
        return true;

    ASSERT(!frameView->needsLayout());

    IntRect containerViewportRect = frameView->visibleContentRect();
    // We want to select a node if it is currently off screen, but will be
    // exposed after we scroll. Adjust the viewport to post-scrolling position.
    // If the container has overflow:hidden, we cannot scroll, so we do not pass direction
    // and we do not adjust for scrolling.
    switch (direction) {
    case FocusDirectionLeft:
        containerViewportRect.setX(containerViewportRect.x() - Scrollbar::pixelsPerLineStep());
        containerViewportRect.setWidth(containerViewportRect.width() + Scrollbar::pixelsPerLineStep());
        break;
    case FocusDirectionRight:
        containerViewportRect.setWidth(containerViewportRect.width() + Scrollbar::pixelsPerLineStep());
        break;
    case FocusDirectionUp:
        containerViewportRect.setY(containerViewportRect.y() - Scrollbar::pixelsPerLineStep());
        containerViewportRect.setHeight(containerViewportRect.height() + Scrollbar::pixelsPerLineStep());
        break;
    case FocusDirectionDown:
        containerViewportRect.setHeight(containerViewportRect.height() + Scrollbar::pixelsPerLineStep());
        break;
    default:
        break;
    }

    RenderObject* render = node->renderer();
    if (!render)
        return true;

    IntRect rect(render->absoluteClippedOverflowRect());
    if (rect.isEmpty())
        return true;

    return !containerViewportRect.intersects(rect);
}
// Checks if |node| is offscreen the visible area (viewport) of its container
// document. In case it is, one can scroll in direction or take any different
// desired action later on.
bool hasOffscreenRect(Node* node)
{
    // Get the FrameView in which |node| is (which means the current viewport if |node|
    // is not in an inner document), so we can check if its content rect is visible
    // before we actually move the focus to it.
    FrameView* frameView = node->document()->view();
    if (!frameView)
        return true;

    IntRect containerViewportRect = frameView->visibleContentRect();

    RenderObject* render = node->renderer();
    if (!render)
        return true;

    IntRect rect(render->absoluteClippedOverflowRect());
    return !containerViewportRect.intersects(rect);
}
Example #9
0
HitTestResult hitTestInDocument(const Document* document, int x, int y)
{
    LocalFrame* frame = document->frame();

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

    IntPoint point(x, y);
    if (!frameView->visibleContentRect().contains(point))
        return HitTestResult();

    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
    HitTestResult result(point);
    document->renderView()->hitTest(request, result);
    return result;
}
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;
}
Example #11
0
HitTestResult hitTestInDocument(const Document* document, int x, int y)
{
    LocalFrame* frame = document->frame();

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

    float scaleFactor = frame->pageZoomFactor();
    IntPoint point = roundedIntPoint(FloatPoint(x * scaleFactor  + frameView->scrollX(), y * scaleFactor + frameView->scrollY()));

    if (!frameView->visibleContentRect().contains(point))
        return HitTestResult();

    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
    HitTestResult result(point);
    document->renderView()->hitTest(request, result);
    return result;
}
Example #12
0
void ChromeClientImpl::popupOpened(PopupContainer* popupContainer,
                                   const IntRect& bounds,
                                   bool handleExternally)
{
    // For Autofill popups, if the popup will not be fully visible, we shouldn't
    // show it at all. Among other things, this prevents users from being able
    // to interact via the keyboard with an invisible popup.
    if (popupContainer->popupType() == PopupContainer::Suggestion) {
        FrameView* view = m_webView->page()->mainFrame()->view();
        IntRect visibleRect = view->visibleContentRect(true /* include scrollbars */);
        // |bounds| is in screen coordinates, so make sure to convert it to
        // content coordinates prior to comparing to |visibleRect|.
        IntRect screenRect = bounds;
        screenRect.setLocation(view->screenToContents(bounds.location()));
        if (!visibleRect.contains(screenRect)) {
            m_webView->hideAutofillPopup();
            return;
        }
    }

    if (!m_webView->client())
        return;

    WebWidget* webwidget;
    if (handleExternally) {
        WebPopupMenuInfo popupInfo;
        getPopupMenuInfo(popupContainer, &popupInfo);
        webwidget = m_webView->client()->createPopupMenu(popupInfo);
    } else {
        webwidget = m_webView->client()->createPopupMenu(
            convertPopupType(popupContainer->popupType()));
        // We only notify when the WebView has to handle the popup, as when
        // the popup is handled externally, the fact that a popup is showing is
        // transparent to the WebView.
        m_webView->popupOpened(popupContainer);
    }
    static_cast<WebPopupMenuImpl*>(webwidget)->init(popupContainer, bounds);
}
Example #13
0
void ViewportAnchor::computeOrigins(const FrameView& frameView, const FloatSize& innerSize,
    IntPoint& mainFrameOffset, FloatPoint& pinchViewportOffset) const
{
    IntSize outerSize = frameView.visibleContentRect().size();

    // Compute the viewport origins in CSS pixels relative to the document.
    FloatSize absPinchViewportOffset = m_normalizedPinchViewportOffset;
    absPinchViewportOffset.scale(outerSize.width(), outerSize.height());

    FloatPoint innerOrigin = getInnerOrigin(innerSize);
    FloatPoint outerOrigin = innerOrigin - absPinchViewportOffset;

    IntRect outerRect = IntRect(flooredIntPoint(outerOrigin), outerSize);
    FloatRect innerRect = FloatRect(innerOrigin, innerSize);

    moveToEncloseRect(outerRect, innerRect);

    outerRect.setLocation(frameView.adjustScrollPositionWithinRange(outerRect.location()));

    moveIntoRect(innerRect, outerRect);

    mainFrameOffset = outerRect.location();
    pinchViewportOffset = FloatPoint(innerRect.location() - outerRect.location());
}
Example #14
0
void DateTimeChooserImpl::writeDocument(WebCore::DocumentWriter& writer)
{
    WebCore::DateComponents date;
    date.setMillisecondsSinceEpochForDate(m_parameters.minimum);
    String minString = date.toString();
    date.setMillisecondsSinceEpochForDate(m_parameters.maximum);
    String maxString = date.toString();
    String stepString = String::number(m_parameters.step);
    String stepBaseString = String::number(m_parameters.stepBase, 11, WTF::TruncateTrailingZeros);
    IntRect anchorRectInScreen = m_chromeClient->rootViewToScreen(m_parameters.anchorRectInRootView);
    FrameView* view = static_cast<WebViewImpl*>(m_chromeClient->webView())->page()->mainFrame()->view();
    IntRect rootViewVisibleContentRect = view->visibleContentRect(true /* include scrollbars */);
    IntRect rootViewRectInScreen = m_chromeClient->rootViewToScreen(rootViewVisibleContentRect);
    rootViewRectInScreen.move(-view->scrollX(), -view->scrollY());

    addString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", writer);
    writer.addData(WebCore::pickerCommonCss, sizeof(WebCore::pickerCommonCss));
    writer.addData(WebCore::suggestionPickerCss, sizeof(WebCore::suggestionPickerCss));
    writer.addData(WebCore::calendarPickerCss, sizeof(WebCore::calendarPickerCss));
    CString extraStyle = WebCore::RenderTheme::defaultTheme()->extraCalendarPickerStyleSheet();
    if (extraStyle.length())
        writer.addData(extraStyle.data(), extraStyle.length());
    addString("</style></head><body><div id=main>Loading...</div><script>\n"
               "window.dialogArguments = {\n", writer);
    addProperty("anchorRectInScreen", anchorRectInScreen, writer);
    addProperty("rootViewRectInScreen", rootViewRectInScreen, writer);
#if OS(MAC_OS_X)
    addProperty("confineToRootView", true, writer);
#else
    addProperty("confineToRootView", false, writer);
#endif
    addProperty("min", minString, writer);
    addProperty("max", maxString, writer);
    addProperty("step", stepString, writer);
    addProperty("stepBase", stepBaseString, writer);
    addProperty("required", m_parameters.required, writer);
    addProperty("currentValue", m_parameters.currentValue, writer);
    addProperty("locale", WebCore::defaultLanguage(), writer);
    addProperty("todayLabel", Platform::current()->queryLocalizedString(WebLocalizedString::CalendarToday), writer);
    addProperty("clearLabel", Platform::current()->queryLocalizedString(WebLocalizedString::CalendarClear), writer);
    addProperty("weekStartDay", m_locale->firstDayOfWeek(), writer);
    addProperty("monthLabels", m_locale->monthLabels(), writer);
    addProperty("dayLabels", m_locale->weekDayShortLabels(), writer);
    addProperty("isCalendarRTL", m_locale->isRTL(), writer);
    addProperty("isRTL", m_parameters.isAnchorElementRTL, writer);
    if (m_parameters.suggestionValues.size()) {
        addProperty("inputWidth", static_cast<unsigned>(m_parameters.anchorRectInRootView.width()), writer);
        addProperty("suggestionValues", m_parameters.suggestionValues, writer);
        addProperty("localizedSuggestionValues", m_parameters.localizedSuggestionValues, writer);
        addProperty("suggestionLabels", m_parameters.suggestionLabels, writer);
        addProperty("showOtherDateEntry", m_parameters.type == WebCore::InputTypeNames::date(), writer);
        addProperty("otherDateLabel", Platform::current()->queryLocalizedString(WebLocalizedString::OtherDateLabel), writer);
        addProperty("suggestionHighlightColor", WebCore::RenderTheme::defaultTheme()->activeListBoxSelectionBackgroundColor().serialized(), writer);
        addProperty("suggestionHighlightTextColor", WebCore::RenderTheme::defaultTheme()->activeListBoxSelectionForegroundColor().serialized(), writer);
    }
    addString("}\n", writer);

    writer.addData(WebCore::pickerCommonJs, sizeof(WebCore::pickerCommonJs));
    writer.addData(WebCore::suggestionPickerJs, sizeof(WebCore::suggestionPickerJs));
    writer.addData(WebCore::calendarPickerJs, sizeof(WebCore::calendarPickerJs));
    addString("</script></body>\n", writer);
}
Example #15
0
PassRefPtr<InspectorObject> InspectorOverlay::buildObjectForHighlightedNode() const
{
    if (!m_highlightNode)
        return nullptr;

    Node* node = m_highlightNode.get();
    RenderObject* renderer = node->renderer();
    if (!renderer)
        return nullptr;

    RefPtr<InspectorArray> highlightFragments = buildObjectForRendererFragments(renderer, m_nodeHighlightConfig);
    if (!highlightFragments)
        return nullptr;

    RefPtr<InspectorObject> highlightObject = InspectorObject::create();

    // The main view's scroll offset is shared across all quads.
    FrameView* mainView = m_page.mainFrame().view();
    highlightObject->setObject("scroll", buildObjectForPoint(!mainView->delegatesScrolling() ? mainView->visibleContentRect().location() : FloatPoint()));

    highlightObject->setArray("fragments", highlightFragments.release());

    if (m_nodeHighlightConfig.showInfo) {
        RefPtr<InspectorObject> elementInfo = buildObjectForElementInfo(node);
        if (elementInfo)
            highlightObject->setObject("elementInfo", elementInfo.release());
    }
        
    return highlightObject.release();
}
Example #16
0
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);
        }
    }
}
void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView& frameView)
{
    ASSERT(isMainThread());
    ASSERT(m_page);

    // If there isn't a root node yet, don't do anything. We'll be called again after creating one.
    if (!m_scrollingStateTree->rootStateNode())
        return;

    // Compute the region of the page that we can't do fast scrolling for. This currently includes
    // all scrollable areas, such as subframes, overflow divs and list boxes. We need to do this even if the
    // frame view whose layout was updated is not the main frame.
    // In the future, we may want to have the ability to set non-fast scrolling regions for more than
    // just the root node. But right now, this concept only applies to the root.
    m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(absoluteNonFastScrollableRegion());
    m_nonFastScrollableRegionDirty = false;

    if (!coordinatesScrollingForFrameView(frameView))
        return;

    ScrollingStateFrameScrollingNode* node = downcast<ScrollingStateFrameScrollingNode>(m_scrollingStateTree->stateNodeForID(frameView.scrollLayerID()));
    if (!node)
        return;

    Scrollbar* verticalScrollbar = frameView.verticalScrollbar();
    Scrollbar* horizontalScrollbar = frameView.horizontalScrollbar();
    node->setScrollbarPaintersFromScrollbars(verticalScrollbar, horizontalScrollbar);
    
    node->setFrameScaleFactor(frameView.frame().frameScaleFactor());
    node->setHeaderHeight(frameView.headerHeight());
    node->setFooterHeight(frameView.footerHeight());
    node->setTopContentInset(frameView.topContentInset());

    node->setScrollOrigin(frameView.scrollOrigin());
    node->setScrollableAreaSize(frameView.visibleContentRect().size());
    node->setTotalContentsSize(frameView.totalContentsSize());
    node->setReachableContentsSize(frameView.totalContentsSize());
    node->setFixedElementsLayoutRelativeToFrame(frameView.fixedElementsLayoutRelativeToFrame());

#if ENABLE(CSS_SCROLL_SNAP)
    frameView.updateSnapOffsets();
    updateScrollSnapPropertiesWithFrameView(frameView);
#endif

#if PLATFORM(COCOA)
    Page* page = frameView.frame().page();
    if (page && page->expectsWheelEventTriggers()) {
        LOG(WheelEventTestTriggers, "    AsyncScrollingCoordinator::frameViewLayoutUpdated: Expects wheel event test trigger=%d", page->expectsWheelEventTriggers());
        node->setExpectsWheelEventTestTrigger(page->expectsWheelEventTriggers());
    }
#endif

    ScrollableAreaParameters scrollParameters;
    scrollParameters.horizontalScrollElasticity = frameView.horizontalScrollElasticity();
    scrollParameters.verticalScrollElasticity = frameView.verticalScrollElasticity();
    scrollParameters.hasEnabledHorizontalScrollbar = horizontalScrollbar && horizontalScrollbar->enabled();
    scrollParameters.hasEnabledVerticalScrollbar = verticalScrollbar && verticalScrollbar->enabled();
    scrollParameters.horizontalScrollbarMode = frameView.horizontalScrollbarMode();
    scrollParameters.verticalScrollbarMode = frameView.verticalScrollbarMode();

    node->setScrollableAreaParameters(scrollParameters);
}
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);
        }
    }
}