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 }