void RenderLayerScrollableArea::setScrollOffset(const IntPoint& newScrollOffset) { // Ensure that the dimensions will be computed if they need to be (for overflow:hidden blocks). if (m_scrollDimensionsDirty) computeScrollDimensions(); if (scrollOffset() == toIntSize(newScrollOffset)) return; setScrollOffset(toIntSize(newScrollOffset)); LocalFrame* frame = box().frame(); ASSERT(frame); RefPtr<FrameView> frameView = box().frameView(); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "ScrollLayer", "data", InspectorScrollLayerEvent::data(&box())); const RenderLayerModelObject* paintInvalidationContainer = box().containerForPaintInvalidation(); // Update the positions of our child layers (if needed as only fixed layers should be impacted by a scroll). // We don't update compositing layers, because we need to do a deep update from the compositing ancestor. if (!frameView->isInPerformLayout()) { // If we're in the middle of layout, we'll just update layers once layout has finished. layer()->clipper().clearClipRectsIncludingDescendants(); box().setPreviousPaintInvalidationRect(box().boundsRectForPaintInvalidation(paintInvalidationContainer)); updateCompositingLayersAfterScroll(); } // The caret rect needs to be invalidated after scrolling frame->selection().setCaretRectNeedsUpdate(); FloatQuad quadForFakeMouseMoveEvent = FloatQuad(layer()->renderer()->previousPaintInvalidationRect()); quadForFakeMouseMoveEvent = paintInvalidationContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent); frame->eventHandler().dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent); // For querying RenderLayer::compositingState() // This code appears correct, since scrolling outside of layout happens during activities that do not dirty compositing state. DisableCompositingQueryAsserts disabler; if (box().frameView()->isInPerformLayout()) box().setShouldDoFullPaintInvalidation(true); else box().invalidatePaintUsingContainer(paintInvalidationContainer, layer()->renderer()->previousPaintInvalidationRect(), InvalidationScroll); // Schedule the scroll DOM event. if (box().node()) box().node()->document().enqueueScrollEventForNode(box().node()); }
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; }
void RotationViewportAnchor::computeOrigins( const FloatSize& innerSize, IntPoint& mainFrameOffset, FloatPoint& visualViewportOffset) const { IntSize outerSize = layoutViewport().visibleContentRect().size(); // Compute the viewport origins in CSS pixels relative to the document. FloatSize absVisualViewportOffset = m_normalizedVisualViewportOffset; absVisualViewportOffset.scale(outerSize.width(), outerSize.height()); FloatPoint innerOrigin = getInnerOrigin(innerSize); FloatPoint outerOrigin = innerOrigin - absVisualViewportOffset; IntRect outerRect = IntRect(flooredIntPoint(outerOrigin), outerSize); FloatRect innerRect = FloatRect(innerOrigin, innerSize); moveToEncloseRect(outerRect, innerRect); outerRect.setLocation(IntPoint( layoutViewport().clampScrollOffset(toIntSize(outerRect.location())))); moveIntoRect(innerRect, outerRect); mainFrameOffset = outerRect.location(); visualViewportOffset = FloatPoint(innerRect.location() - outerRect.location()); }
IntPoint ScrollableArea::constrainScrollPositionForOverhang(const IntRect& visibleContentRect, const IntSize& totalContentsSize, const IntPoint& scrollPosition, const IntPoint& scrollOrigin, int headerHeight, int footerHeight) { // The viewport rect that we're scrolling shouldn't be larger than our document. IntSize idealScrollRectSize(std::min(visibleContentRect.width(), totalContentsSize.width()), std::min(visibleContentRect.height(), totalContentsSize.height())); IntRect scrollRect(scrollPosition + scrollOrigin - IntSize(0, headerHeight), idealScrollRectSize); IntRect documentRect(IntPoint(), IntSize(totalContentsSize.width(), totalContentsSize.height() - headerHeight - footerHeight)); // Use intersection to constrain our ideal scroll rect by the document rect. scrollRect.intersect(documentRect); if (scrollRect.size() != idealScrollRectSize) { // If the rect was clipped, restore its size, effectively pushing it "down" from the top left. scrollRect.setSize(idealScrollRectSize); // If we still clip, push our rect "up" from the bottom right. scrollRect.intersect(documentRect); if (scrollRect.width() < idealScrollRectSize.width()) scrollRect.move(-(idealScrollRectSize.width() - scrollRect.width()), 0); if (scrollRect.height() < idealScrollRectSize.height()) scrollRect.move(0, -(idealScrollRectSize.height() - scrollRect.height())); } return scrollRect.location() - toIntSize(scrollOrigin); }
static void applyClipRects(const ClipRectsContext& context, const LayoutObject& layoutObject, LayoutPoint offset, ClipRects& clipRects) { ASSERT(layoutObject.hasOverflowClip() || layoutObject.hasClip() || layoutObject.style()->containsPaint()); LayoutView* view = layoutObject.view(); ASSERT(view); if (clipRects.fixed() && context.rootLayer->layoutObject() == view) offset -= toIntSize(view->frameView()->scrollPosition()); if (layoutObject.hasOverflowClip() || layoutObject.style()->containsPaint()) { ClipRect newOverflowClip = toLayoutBox(layoutObject).overflowClipRect(offset, context.scrollbarRelevancy); newOverflowClip.setHasRadius(layoutObject.style()->hasBorderRadius()); clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect())); if (layoutObject.isPositioned()) clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect())); if (layoutObject.isLayoutView()) clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.fixedClipRect())); if (layoutObject.style()->containsPaint()) { clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect())); clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.fixedClipRect())); } } if (layoutObject.hasClip()) { LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset); clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()).setIsClippedByClipCss()); clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()).setIsClippedByClipCss()); clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect()).setIsClippedByClipCss()); } }
void ViewClientEfl::didRenderFrame(WKViewRef, WKSize contentsSize, WKRect coveredRect, const void* clientInfo) { EwkView* ewkView = toEwkView(clientInfo); if (WKPageUseFixedLayout(ewkView->wkPage())) ewkView->pageViewportController().didRenderFrame(toIntSize(contentsSize), toIntRect(coveredRect)); else ewkView->scheduleUpdateDisplay(); }
void ViewClientEfl::didChangeContentsSize(WKViewRef, WKSize size, const void* clientInfo) { EwkView* ewkView = toEwkView(clientInfo); if (WKPageUseFixedLayout(ewkView->wkPage())) ewkView->pageViewportController().didChangeContentsSize(toIntSize(size)); else ewkView->scheduleUpdateDisplay(); ewkView->smartCallback<ContentsSizeChanged>().call(size); }
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; }
IntSize WebFrame::scrollOffset() const { if (!m_coreFrame) return IntSize(); FrameView* view = m_coreFrame->view(); if (!view) return IntSize(); return toIntSize(view->scrollPosition()); }
void RenderLayerScrollableArea::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls) { // Don't do anything if we have no overflow. if (!box().hasOverflowClip()) return; IntPoint adjustedPaintOffset = paintOffset; if (paintingOverlayControls) adjustedPaintOffset = m_cachedOverlayScrollbarOffset; // Move the scrollbar widgets if necessary. We normally move and resize widgets during layout, // but sometimes widgets can move without layout occurring (most notably when you scroll a // document that contains fixed positioned elements). positionOverflowControls(toIntSize(adjustedPaintOffset)); // Overlay scrollbars paint in a second pass through the layer tree so that they will paint // on top of everything else. If this is the normal painting pass, paintingOverlayControls // will be false, and we should just tell the root layer that there are overlay scrollbars // that need to be painted. That will cause the second pass through the layer tree to run, // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the // second pass doesn't need to re-enter the RenderTree to get it right. if (hasOverlayScrollbars() && !paintingOverlayControls) { m_cachedOverlayScrollbarOffset = paintOffset; IntRect localDamgeRect = damageRect; localDamgeRect.moveBy(-paintOffset); if (!overflowControlsIntersectRect(localDamgeRect)) return; RenderView* renderView = box().view(); RenderLayer* paintingRoot = layer()->enclosingLayerWithCompositedLayerMapping(IncludeSelf); if (!paintingRoot) paintingRoot = renderView->layer(); paintingRoot->setContainsDirtyOverlayScrollbars(true); return; } // This check is required to avoid painting custom CSS scrollbars twice. if (paintingOverlayControls && !hasOverlayScrollbars()) return; // Now that we're sure the scrollbars are in the right place, paint them. if (m_hBar) m_hBar->paint(context, damageRect); if (m_vBar) m_vBar->paint(context, damageRect); }
LayoutRect RenderLayerScrollableArea::exposeRect(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY) { LayoutRect localExposeRect(box().absoluteToLocalQuad(FloatQuad(FloatRect(rect)), UseTransforms).boundingBox()); LayoutRect layerBounds(0, 0, box().clientWidth(), box().clientHeight()); LayoutRect r = ScrollAlignment::getRectToExpose(layerBounds, localExposeRect, alignX, alignY); IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset() + toIntSize(roundedIntRect(r).location())); if (clampedScrollOffset == adjustedScrollOffset()) return rect; IntSize oldScrollOffset = adjustedScrollOffset(); scrollToOffset(clampedScrollOffset); IntSize scrollOffsetDifference = adjustedScrollOffset() - oldScrollOffset; localExposeRect.move(-scrollOffsetDifference); return LayoutRect(box().localToAbsoluteQuad(FloatQuad(FloatRect(localExposeRect)), UseTransforms).boundingBox()); }
ClipRect PaintLayerClipper::backgroundClipRect(const ClipRectsContext& context) const { ASSERT(m_layoutObject.layer()->parent()); ASSERT(m_layoutObject.view()); RefPtr<ClipRects> parentClipRects = ClipRects::create(); if (m_layoutObject.layer() == context.rootLayer) parentClipRects->reset(LayoutRect(LayoutRect::infiniteIntRect())); else m_layoutObject.layer()->parent()->clipper().getOrCalculateClipRects(context, *parentClipRects); ClipRect result = backgroundClipRectForPosition(*parentClipRects, m_layoutObject.style()->position()); // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite. if (parentClipRects->fixed() && context.rootLayer->layoutObject() == m_layoutObject.view() && result != LayoutRect(LayoutRect::infiniteIntRect())) result.move(toIntSize(m_layoutObject.view()->frameView()->scrollPosition())); return result; }
void ScrollableArea::scrollIntoRect(const LayoutRect& rectInContent, const FloatRect& targetRectInFrame) { // Use |pixelSnappedIntRect| for rounding to pixel as opposed to |enclosingIntRect|. It gives a better // combined (location and size) rounding error resulting in a more accurate scroll offset. // FIXME: It would probably be best to do the whole calculation in LayoutUnits but contentsToRootFrame // and friends don't have LayoutRect/Point versions yet. IntRect boundsInContent = pixelSnappedIntRect(rectInContent); IntRect boundsInFrame(boundsInContent.location() - toIntSize(scrollPosition()), boundsInContent.size()); int centeringOffsetX = (targetRectInFrame.width() - boundsInFrame.width()) / 2; int centeringOffsetY = (targetRectInFrame.height() - boundsInFrame.height()) / 2; IntSize scrollDelta( boundsInFrame.x() - centeringOffsetX - targetRectInFrame.x(), boundsInFrame.y() - centeringOffsetY - targetRectInFrame.y()); DoublePoint targetOffset = DoublePoint(scrollPosition() + scrollDelta); setScrollPosition(targetOffset, ProgrammaticScroll); }
IntPoint VisualViewport::clampDocumentOffsetAtScale(const IntPoint& offset, float scale) { if (!mainFrame() || !mainFrame()->view()) return IntPoint(); FrameView* view = mainFrame()->view(); FloatSize scaledSize(m_size); scaledSize.scale(1 / scale); IntSize visualViewportMax = flooredIntSize(FloatSize(contentsSize()) - scaledSize); IntSize max = view->maximumScrollOffsetInt() + visualViewportMax; IntSize min = view->minimumScrollOffsetInt(); // VisualViewportMin should be (0, 0) IntSize clamped = toIntSize(offset); clamped = clamped.shrunkTo(max); clamped = clamped.expandedTo(min); return IntPoint(clamped); }
bool MouseWheelRegionOverlay::updateRegion() { std::unique_ptr<Region> region = std::make_unique<Region>(); for (const Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext()) { if (!frame->view() || !frame->document()) continue; Document::RegionFixedPair frameRegion = frame->document()->absoluteRegionForEventTargets(frame->document()->wheelEventTargets()); IntPoint frameOffset = frame->view()->contentsToRootView(IntPoint()); frameRegion.first.translate(toIntSize(frameOffset)); region->unite(frameRegion.first); } region->translate(m_overlay->viewToOverlayOffset()); bool regionChanged = !m_region || !(*m_region == *region); m_region = WTFMove(region); return regionChanged; }
void NonCompositedContentHost::setViewport(const WebCore::IntSize& viewportSize, const WebCore::IntSize& contentsSize, const WebCore::IntPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin) { if (!haveScrollLayer()) return; bool visibleRectChanged = m_viewportSize != viewportSize; m_viewportSize = viewportSize; WebLayer* layer = scrollLayer(); layer->setScrollPosition(scrollPosition + scrollOrigin); layer->setPosition(WebFloatPoint(-scrollPosition)); // Due to the possibility of pinch zoom, the noncomposited layer is always // assumed to be scrollable. layer->setScrollable(true); m_graphicsLayer->setSize(contentsSize); // In RTL-style pages, the origin of the initial containing block for the // root layer may be positive; translate the layer to avoid negative // coordinates. m_layerAdjust = -toIntSize(scrollOrigin); if (m_graphicsLayer->transform().m41() != m_layerAdjust.width() || m_graphicsLayer->transform().m42() != m_layerAdjust.height()) { WebCore::TransformationMatrix transform = m_graphicsLayer->transform(); transform.setM41(m_layerAdjust.width()); transform.setM42(m_layerAdjust.height()); m_graphicsLayer->setTransform(transform); // If a tiled layer is shifted left or right, the content that goes into // each tile will change. Invalidate the entire layer when this happens. m_graphicsLayer->setNeedsDisplay(); } else if (visibleRectChanged) m_graphicsLayer->setNeedsDisplay(); WebCore::GraphicsLayer* clipLayer = m_graphicsLayer->parent()->parent(); WebCore::GraphicsLayer* rootLayer = clipLayer; while (rootLayer->parent()) rootLayer = rootLayer->parent(); setScrollbarBoundsContainPageScale(rootLayer, clipLayer); }
void GraphicsLayer::didScroll() { if (m_scrollableArea) m_scrollableArea->scrollToOffsetWithoutAnimation(m_scrollableArea->minimumScrollPosition() + toIntSize(m_layer->layer()->scrollPosition())); }
WebTouchEvent WebEventFactory::createWebTouchEvent(const EwkTouchEvent* event, const AffineTransform& toWebContent) { API::Array* touchPointsArray = toImpl(event->touchPoints()); size_t size = touchPointsArray->size(); Vector<WebPlatformTouchPoint> touchPoints; touchPoints.reserveInitialCapacity(size); for (size_t i = 0; i < size; ++i) { if (EwkTouchPoint* point = touchPointsArray->at<EwkTouchPoint>(i)) touchPoints.uncheckedAppend(WebPlatformTouchPoint(point->id(), toWebPlatformTouchPointState(point->state()), toIntPoint(point->screenPosition()), toWebContent.mapPoint(toIntPoint(point->position())), toIntSize(point->radius()), point->rotationAngle(), point->forceFactor())); } return WebTouchEvent(toWebEventType(event->eventType()), touchPoints, toWebEventModifiers(event->modifiers()), event->timestamp()); }
Region ScrollingCoordinator::absoluteNonFastScrollableRegionForFrame(const Frame& frame) const { RenderView* renderView = frame.contentRenderer(); if (!renderView || renderView->documentBeingDestroyed()) return Region(); #if ENABLE(IOS_TOUCH_EVENTS) // On iOS, we use nonFastScrollableRegion to represent the region covered by elements with touch event handlers. ASSERT(frame.isMainFrame()); Document* document = frame.document(); if (!document) return Region(); Vector<IntRect> touchRects; document->getTouchRects(touchRects); Region touchRegion; for (const auto& rect : touchRects) touchRegion.unite(rect); // FIXME: use absoluteRegionForEventTargets(). return touchRegion; #else Region nonFastScrollableRegion; FrameView* frameView = frame.view(); if (!frameView) return nonFastScrollableRegion; // FIXME: should ASSERT(!frameView->needsLayout()) here, but need to fix DebugPageOverlays // to not ask for regions at bad times. if (const FrameView::ScrollableAreaSet* scrollableAreas = frameView->scrollableAreas()) { for (auto& scrollableArea : *scrollableAreas) { // Composited scrollable areas can be scrolled off the main thread. if (scrollableArea->usesAsyncScrolling()) continue; bool isInsideFixed; IntRect box = scrollableArea->scrollableAreaBoundingBox(&isInsideFixed); if (isInsideFixed) box = IntRect(frameView->fixedScrollableAreaBoundsInflatedForScrolling(LayoutRect(box))); nonFastScrollableRegion.unite(box); } } for (auto& widget : frameView->widgetsInRenderTree()) { RenderWidget* renderWidget = RenderWidget::find(widget); if (!renderWidget || !is<PluginViewBase>(*widget)) continue; if (downcast<PluginViewBase>(*widget).wantsWheelEvents()) nonFastScrollableRegion.unite(renderWidget->absoluteBoundingBoxRect()); } // FIXME: if we've already accounted for this subframe as a scrollable area, we can avoid recursing into it here. for (Frame* subframe = frame.tree().firstChild(); subframe; subframe = subframe->tree().nextSibling()) { FrameView* subframeView = subframe->view(); if (!subframeView) continue; Region subframeRegion = absoluteNonFastScrollableRegionForFrame(*subframe); // Map from the frame document to our document. IntPoint offset = subframeView->contentsToContainingViewContents(IntPoint()); // FIXME: this translation ignores non-trival transforms on the frame. subframeRegion.translate(toIntSize(offset)); nonFastScrollableRegion.unite(subframeRegion); } Document::RegionFixedPair wheelHandlerRegion = frame.document()->absoluteRegionForEventTargets(frame.document()->wheelEventTargets()); bool wheelHandlerInFixedContent = wheelHandlerRegion.second; if (wheelHandlerInFixedContent) { // FIXME: need to handle position:sticky here too. LayoutRect inflatedWheelHandlerBounds = frameView->fixedScrollableAreaBoundsInflatedForScrolling(LayoutRect(wheelHandlerRegion.first.bounds())); wheelHandlerRegion.first.unite(enclosingIntRect(inflatedWheelHandlerBounds)); } nonFastScrollableRegion.unite(wheelHandlerRegion.first); // FIXME: If this is not the main frame, we could clip the region to the frame's bounds. return nonFastScrollableRegion; #endif }
ScrollPosition ScrollableArea::scrollPositionFromOffset(ScrollOffset offset) const { return scrollPositionFromOffset(offset, toIntSize(m_scrollOrigin)); }
ScrollOffset ScrollableArea::scrollOffsetFromPosition(ScrollPosition position) const { return scrollOffsetFromPosition(position, toIntSize(m_scrollOrigin)); }