void Frame::scrollOverflowLayer(RenderLayer* layer, const IntRect& visibleRect, const IntRect& exposeRect) { if (!layer) return; RenderBox* box = layer->renderBox(); if (!box) return; if (visibleRect.intersects(exposeRect)) return; // FIXME: Why isn't this just calling RenderLayer::scrollRectToVisible()? ScrollOffset scrollOffset = layer->scrollOffset(); int exposeLeft = exposeRect.x(); int exposeRight = exposeLeft + exposeRect.width(); int clientWidth = roundToInt(box->clientWidth()); if (exposeLeft <= 0) scrollOffset.setX(std::max(0, scrollOffset.x() + exposeLeft - clientWidth / 2)); else if (exposeRight >= clientWidth) scrollOffset.setX(std::min(box->scrollWidth() - clientWidth, scrollOffset.x() + clientWidth / 2)); int exposeTop = exposeRect.y(); int exposeBottom = exposeTop + exposeRect.height(); int clientHeight = roundToInt(box->clientHeight()); if (exposeTop <= 0) scrollOffset.setY(std::max(0, scrollOffset.y() + exposeTop - clientHeight / 2)); else if (exposeBottom >= clientHeight) scrollOffset.setY(std::min(box->scrollHeight() - clientHeight, scrollOffset.y() + clientHeight / 2)); layer->scrollToOffset(scrollOffset); selection().setCaretRectNeedsUpdate(); selection().updateAppearance(); }
void Frame::scrollOverflowLayer(RenderLayer* layer, const IntRect& visibleRect, const IntRect& exposeRect) { if (!layer) return; RenderBox* box = layer->renderBox(); if (!box) return; if (visibleRect.intersects(exposeRect)) return; int x = layer->scrollXOffset(); int exposeLeft = exposeRect.x(); int exposeRight = exposeLeft + exposeRect.width(); int clientWidth = roundToInt(box->clientWidth()); if (exposeLeft <= 0) x = std::max(0, x + exposeLeft - clientWidth / 2); else if (exposeRight >= clientWidth) x = std::min(box->scrollWidth() - clientWidth, x + clientWidth / 2); int y = layer->scrollYOffset(); int exposeTop = exposeRect.y(); int exposeBottom = exposeTop + exposeRect.height(); int clientHeight = roundToInt(box->clientHeight()); if (exposeTop <= 0) y = std::max(0, y + exposeTop - clientHeight / 2); else if (exposeBottom >= clientHeight) y = std::min(box->scrollHeight() - clientHeight, y + clientHeight / 2); layer->scrollToOffset(IntSize(x, y)); selection().setCaretRectNeedsUpdate(); selection().updateAppearance(); }
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 } }
static bool isElementLargeEnoughForMainContent(const HTMLMediaElement& element) { static const double elementMainContentAreaMinimum = 400 * 300; static const double maximumAspectRatio = 1.8; // Slightly larger than 16:9. static const double minimumAspectRatio = .5; // Slightly smaller than 16:9. // Elements which have not yet been laid out, or which are not yet in the DOM, cannot be main content. RenderBox* renderer = downcast<RenderBox>(element.renderer()); if (!renderer) return false; double width = renderer->clientWidth(); double height = renderer->clientHeight(); double area = width * height; double aspectRatio = width / height; return area >= elementMainContentAreaMinimum && aspectRatio >= minimumAspectRatio && aspectRatio <= maximumAspectRatio; }
int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge) { RenderBox* box = m_layer->renderBox(); ASSERT(box); RenderStyle* s = box->style(); if (isHorizontal()) { bool ltr = s->direction() == LTR; int clientWidth = box->clientWidth(); int contentWidth = ltr ? box->rightmostPosition(true, false) : box->leftmostPosition(true, false); if (ltr) contentWidth += (box->paddingRight() - box->borderLeft()); else { contentWidth = box->width() - contentWidth; contentWidth += (box->paddingLeft() - box->borderRight()); } if (dir == MRIGHT) { if (stopAtContentEdge) return max(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth)); else return ltr ? contentWidth : clientWidth; } else { if (stopAtContentEdge) return min(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth)); else return ltr ? -clientWidth : -contentWidth; } } else { int contentHeight = box->lowestPosition(true, false) - box->borderTop() + box->paddingBottom(); int clientHeight = box->clientHeight(); if (dir == MUP) { if (stopAtContentEdge) return min(contentHeight - clientHeight, 0); else return -clientHeight; } else { if (stopAtContentEdge) return max(contentHeight - clientHeight, 0); else return contentHeight; } } }
int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge) { RenderBox* box = m_layer->renderBox(); ASSERT(box); RenderStyle* s = box->style(); if (isHorizontal()) { bool ltr = s->isLeftToRightDirection(); LayoutUnit clientWidth = box->clientWidth(); LayoutUnit contentWidth = ltr ? box->maxPreferredLogicalWidth() : box->minPreferredLogicalWidth(); if (ltr) contentWidth += (box->paddingRight() - box->borderLeft()); else { contentWidth = box->width() - contentWidth; contentWidth += (box->paddingLeft() - box->borderRight()); } if (dir == MRIGHT) { if (stopAtContentEdge) return max<LayoutUnit>(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth)); else return ltr ? contentWidth : clientWidth; } else { if (stopAtContentEdge) return min<LayoutUnit>(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth)); else return ltr ? -clientWidth : -contentWidth; } } else { int contentHeight = box->layoutOverflowRect().maxY() - box->borderTop() + box->paddingBottom(); int clientHeight = box->clientHeight(); if (dir == MUP) { if (stopAtContentEdge) return min(contentHeight - clientHeight, 0); else return -clientHeight; } else { if (stopAtContentEdge) return max(contentHeight - clientHeight, 0); else return contentHeight; } } }
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); } } }
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); } } }