Region ScrollingCoordinator::computeNonFastScrollableRegion(const Frame* frame, const IntPoint& frameLocation) const { #if ENABLE(IOS_TOUCH_EVENTS) // On iOS, we use nonFastScrollableRegion to represent the region covered by elements with touch event handlers. ASSERT(frame->isMainFrame()); UNUSED_PARAM(frameLocation); Document* document = frame->document(); if (!document) return Region(); Vector<IntRect> touchRects; document->getTouchRects(touchRects); Region touchRegion; for (const auto& rect : touchRects) touchRegion.unite(rect); return touchRegion; #else Region nonFastScrollableRegion; FrameView* frameView = frame->view(); if (!frameView) return nonFastScrollableRegion; IntPoint offset = frameLocation; offset.moveBy(frameView->frameRect().location()); offset.move(0, frameView->topContentInset()); if (const FrameView::ScrollableAreaSet* scrollableAreas = frameView->scrollableAreas()) { for (FrameView::ScrollableAreaSet::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) { ScrollableArea* scrollableArea = *it; // Composited scrollable areas can be scrolled off the main thread. if (scrollableArea->usesCompositedScrolling()) continue; IntRect box = scrollableArea->scrollableAreaBoundingBox(); box.moveBy(offset); nonFastScrollableRegion.unite(box); } } for (const auto& child : frameView->children()) { if (!child->isPluginViewBase()) continue; PluginViewBase* pluginViewBase = toPluginViewBase(child.get()); if (pluginViewBase->wantsWheelEvents()) nonFastScrollableRegion.unite(pluginViewBase->frameRect()); } for (Frame* subframe = frame->tree().firstChild(); subframe; subframe = subframe->tree().nextSibling()) nonFastScrollableRegion.unite(computeNonFastScrollableRegion(subframe, offset)); return nonFastScrollableRegion; #endif }
// Return a set of rectangles that should not be overdrawn by the // plugin ("cutouts"). This helps implement the "iframe shim" // technique of overlaying a windowed plugin with content from the // page. In a nutshell, iframe elements should occlude plugins when // they occur higher in the stacking order. void getPluginOcclusions(Element* element, Widget* parentWidget, const IntRect& frameRect, Vector<IntRect>& occlusions) { RenderObject* pluginNode = element->renderer(); ASSERT(pluginNode); if (!pluginNode->style()) return; Vector<const RenderObject*> pluginZstack; Vector<const RenderObject*> iframeZstack; getObjectStack(pluginNode, &pluginZstack); if (!parentWidget->isFrameView()) return; FrameView* parentFrameView = toFrameView(parentWidget); // Occlusions by iframes. const FrameView::ChildrenWidgetSet* children = parentFrameView->children(); for (FrameView::ChildrenWidgetSet::const_iterator it = children->begin(); it != children->end(); ++it) { // We only care about FrameView's because iframes show up as FrameViews. if (!(*it)->isFrameView()) continue; const FrameView* frameView = toFrameView(it->get()); // Check to make sure we can get both the element and the RenderObject // for this FrameView, if we can't just move on to the next object. // FIXME: Plugin occlusion by remote frames is probably broken. HTMLElement* element = frameView->frame().deprecatedLocalOwner(); if (!element || !element->renderer()) continue; RenderObject* iframeRenderer = element->renderer(); if (isHTMLIFrameElement(*element) && intersectsRect(iframeRenderer, frameRect)) { getObjectStack(iframeRenderer, &iframeZstack); if (iframeIsAbovePlugin(iframeZstack, pluginZstack)) addToOcclusions(toRenderBox(iframeRenderer), occlusions); } } // Occlusions by top layer elements. // FIXME: There's no handling yet for the interaction between top layer and // iframes. For example, a plugin in the top layer will be occluded by an // iframe. And a plugin inside an iframe in the top layer won't be respected // as being in the top layer. const Element* ancestor = topLayerAncestor(element); Document* document = parentFrameView->frame().document(); const WillBeHeapVector<RefPtrWillBeMember<Element> >& elements = document->topLayerElements(); size_t start = ancestor ? elements.find(ancestor) + 1 : 0; for (size_t i = start; i < elements.size(); ++i) addTreeToOcclusions(elements[i]->renderer(), frameRect, occlusions); }
Region ScrollingCoordinator::computeNonFastScrollableRegion(const Frame* frame, const IntPoint& frameLocation) const { Region nonFastScrollableRegion; FrameView* frameView = frame->view(); if (!frameView) return nonFastScrollableRegion; IntPoint offset = frameLocation; offset.moveBy(frameView->frameRect().location()); if (const FrameView::ScrollableAreaSet* scrollableAreas = frameView->scrollableAreas()) { for (FrameView::ScrollableAreaSet::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) { ScrollableArea* scrollableArea = *it; #if USE(ACCELERATED_COMPOSITING) // Composited scrollable areas can be scrolled off the main thread. if (scrollableArea->usesCompositedScrolling()) continue; #endif IntRect box = scrollableArea->scrollableAreaBoundingBox(); box.moveBy(offset); nonFastScrollableRegion.unite(box); } } for (auto it = frameView->children().begin(), end = frameView->children().end(); it != end; ++it) { if (!(*it)->isPluginViewBase()) continue; PluginViewBase* pluginViewBase = toPluginViewBase((*it).get()); if (pluginViewBase->wantsWheelEvents()) nonFastScrollableRegion.unite(pluginViewBase->frameRect()); } for (Frame* subframe = frame->tree().firstChild(); subframe; subframe = subframe->tree().nextSibling()) nonFastScrollableRegion.unite(computeNonFastScrollableRegion(subframe, offset)); return nonFastScrollableRegion; }
// Return a set of rectangles that should not be overdrawn by the // plugin ("cutouts"). This helps implement the "iframe shim" // technique of overlaying a windowed plugin with content from the // page. In a nutshell, iframe elements should occlude plugins when // they occur higher in the stacking order. void WebPluginContainerImpl::windowCutOutRects(const IntRect& frameRect, Vector<IntRect>& cutOutRects) { RenderObject* pluginNode = m_element->renderer(); ASSERT(pluginNode); if (!pluginNode->style()) return; Vector<const RenderObject*> pluginZstack; Vector<const RenderObject*> iframeZstack; getObjectStack(pluginNode, &pluginZstack); // Get the parent widget Widget* parentWidget = this->parent(); if (!parentWidget->isFrameView()) return; FrameView* parentFrameView = static_cast<FrameView*>(parentWidget); const HashSet<RefPtr<Widget> >* children = parentFrameView->children(); for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != children->end(); ++it) { // We only care about FrameView's because iframes show up as FrameViews. if (!(*it)->isFrameView()) continue; const FrameView* frameView = static_cast<const FrameView*>((*it).get()); // Check to make sure we can get both the element and the RenderObject // for this FrameView, if we can't just move on to the next object. if (!frameView->frame() || !frameView->frame()->ownerElement() || !frameView->frame()->ownerElement()->renderer()) continue; HTMLElement* element = frameView->frame()->ownerElement(); RenderObject* iframeRenderer = element->renderer(); if (element->hasTagName(HTMLNames::iframeTag) && iframeRenderer->absoluteBoundingBoxRect().intersects(frameRect) && (!iframeRenderer->style() || iframeRenderer->style()->visibility() == VISIBLE)) { getObjectStack(iframeRenderer, &iframeZstack); if (checkStackOnTop(iframeZstack, pluginZstack)) { IntPoint point = roundedIntPoint(iframeRenderer->localToAbsolute()); RenderBox* rbox = toRenderBox(iframeRenderer); IntSize size(rbox->width(), rbox->height()); cutOutRects.append(IntRect(point, size)); } } } }
void Page::collectPluginViews(Vector<RefPtr<PluginViewBase>, 32>& pluginViewBases) { for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) { FrameView* view = frame->view(); if (!view) return; const HashSet<RefPtr<Widget> >* children = view->children(); ASSERT(children); HashSet<RefPtr<Widget> >::const_iterator end = children->end(); for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) { Widget* widget = (*it).get(); if (widget->isPluginViewBase()) pluginViewBases.append(toPluginViewBase(widget)); } } }