PassRefPtr<WebImage> InjectedBundleRangeHandle::renderedImage(SnapshotOptions options) { Document& ownerDocument = m_range->ownerDocument(); Frame* frame = ownerDocument.frame(); if (!frame) return nullptr; FrameView* frameView = frame->view(); if (!frameView) return nullptr; Ref<Frame> protector(*frame); VisibleSelection oldSelection = frame->selection().selection(); frame->selection().setSelection(VisibleSelection(*m_range)); float scaleFactor = (options & SnapshotOptionsExcludeDeviceScaleFactor) ? 1 : frame->page()->deviceScaleFactor(); IntRect paintRect = enclosingIntRect(m_range->absoluteBoundingRect()); IntSize backingStoreSize = paintRect.size(); backingStoreSize.scale(scaleFactor); RefPtr<ShareableBitmap> backingStore = ShareableBitmap::createShareable(backingStoreSize, ShareableBitmap::SupportsAlpha); if (!backingStore) return nullptr; auto graphicsContext = backingStore->createGraphicsContext(); graphicsContext->scale(scaleFactor); paintRect.move(frameView->frameRect().x(), frameView->frameRect().y()); paintRect.moveBy(-frameView->scrollPosition()); graphicsContext->translate(-paintRect.x(), -paintRect.y()); PaintBehavior oldPaintBehavior = frameView->paintBehavior(); PaintBehavior paintBehavior = oldPaintBehavior | PaintBehaviorSelectionOnly | PaintBehaviorFlattenCompositingLayers; if (options & SnapshotOptionsForceBlackText) paintBehavior |= PaintBehaviorForceBlackText; if (options & SnapshotOptionsForceWhiteText) paintBehavior |= PaintBehaviorForceWhiteText; frameView->setPaintBehavior(paintBehavior); ownerDocument.updateLayout(); frameView->paint(*graphicsContext, paintRect); frameView->setPaintBehavior(oldPaintBehavior); frame->selection().setSelection(oldSelection); return WebImage::create(backingStore); }
void PluginView::updatePluginWidget() { if (!parent() || !m_isWindowed || !platformPluginWidget()) return; ASSERT(parent()->isFrameView()); FrameView* frameView = static_cast<FrameView*>(parent()); IntRect oldWindowRect = m_windowRect; IntRect oldClipRect = m_clipRect; m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); m_clipRect = windowClipRect(); m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) return; // do not call setNPWindowIfNeeded immediately, will be called on paint() m_hasPendingGeometryChange = true; // in order to move/resize the plugin window at the same time as the // rest of frame during e.g. scrolling, we set the window geometry // in the paint() function, but as paint() isn't called when the // plugin window is outside the frame which can be caused by a // scroll, we need to move/resize immediately. if (!m_windowRect.intersects(frameView->frameRect())) setNPWindowIfNeeded(); }
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 }
void PluginView::updatePluginWidget() { if (!parent()) return; ASSERT(parent()->isFrameView()); FrameView* frameView = static_cast<FrameView*>(parent()); IntRect oldWindowRect = m_windowRect; IntRect oldClipRect = m_clipRect; m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); m_clipRect = windowClipRect(); m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) return; // The plugin had a zero width or height before but was resized, we need to show it again. if (oldWindowRect.isEmpty()) show(); if (!m_isWindowed && m_windowRect.size() != oldWindowRect.size()) { if (m_drawable) XFreePixmap(QX11Info::display(), m_drawable); m_drawable = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), m_windowRect.width(), m_windowRect.height(), ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth); QApplication::syncX(); // make sure that the server knows about the Drawable } // do not call setNPWindowIfNeeded immediately, will be called on paint() m_hasPendingGeometryChange = true; // (i) in order to move/resize the plugin window at the same time as the // rest of frame during e.g. scrolling, we set the window geometry // in the paint() function, but as paint() isn't called when the // plugin window is outside the frame which can be caused by a // scroll, we need to move/resize immediately. // (ii) if we are running layout tests from DRT, paint() won't ever get called // so we need to call setNPWindowIfNeeded() if window geometry has changed if (!m_windowRect.intersects(frameView->frameRect()) || (s_isRunningUnderDRT && platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect))) setNPWindowIfNeeded(); if (!m_platformLayer) { // Make sure we get repainted afterwards. This is necessary for downward // scrolling to move the plugin widget properly. // Note that we don't invalidate the frameRect() here. This is because QWebFrame::renderRelativeCoords() // imitates ScrollView and adds the scroll offset back on to the rect we damage here (making the co-ordinates absolute // to the frame again) before passing it to FrameView. invalidate(); } }
void PluginView::updatePluginWidget() { if (!parent()) return; ASSERT(parent()->isFrameView()); FrameView* frameView = toFrameView(parent()); IntRect oldWindowRect = m_windowRect; IntRect oldClipRect = m_clipRect; m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); m_clipRect = windowClipRect(); m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) return; // The plugin had a zero width or height before but was resized, we need to show it again. if (oldWindowRect.isEmpty()) show(); if (!m_isWindowed && m_windowRect.size() != oldWindowRect.size()) { if (m_drawable) XFreePixmap(x11Display(), m_drawable); m_drawable = XCreatePixmap(x11Display(), rootWindowID(), m_windowRect.width(), m_windowRect.height(), ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth); syncX(); // make sure that the server knows about the Drawable } // do not call setNPWindowIfNeeded immediately, will be called on paint() m_hasPendingGeometryChange = true; // (i) in order to move/resize the plugin window at the same time as the // rest of frame during e.g. scrolling, we set the window geometry // in the paint() function, but as paint() isn't called when the // plugin window is outside the frame which can be caused by a // scroll, we need to move/resize immediately. // (ii) if we are running layout tests from DRT, paint() won't ever get called // so we need to call setNPWindowIfNeeded() if window geometry has changed if (!m_windowRect.intersects(frameView->frameRect()) || (s_isRunningUnderDRT && platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect))) setNPWindowIfNeeded(); invalidate(); }
void PageWidgetDelegate::layout(Page* page) { FrameView* view = mainFrameView(page); if (!view) return; // In order for our child HWNDs (NativeWindowWidgets) to update properly, // they need to be told that we are updating the screen. The problem is that // the native widgets need to recalculate their clip region and not overlap // any of our non-native widgets. To force the resizing, call // setFrameRect(). This will be a quick operation for most frames, but the // NativeWindowWidgets will update a proper clipping region. view->setFrameRect(view->frameRect()); // setFrameRect may have the side-effect of causing existing page layout to // be invalidated, so layout needs to be called last. view->updateLayoutAndStyleIfNeededRecursive(); }
Region ScrollingCoordinator::computeNonFastScrollableRegion(Frame* frame, const IntPoint& frameLocation) { 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); } } if (const HashSet<RefPtr<Widget> >* children = frameView->children()) { for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(), end = children->end(); it != end; ++it) { if (!(*it)->isPluginViewBase()) continue; PluginViewBase* pluginViewBase = static_cast<PluginViewBase*>((*it).get()); if (pluginViewBase->wantsWheelEvents()) nonFastScrollableRegion.unite(pluginViewBase->frameRect()); } } FrameTree* tree = frame->tree(); for (Frame* subFrame = tree->firstChild(); subFrame; subFrame = subFrame->tree()->nextSibling()) nonFastScrollableRegion.unite(computeNonFastScrollableRegion(subFrame, offset)); return nonFastScrollableRegion; }
void PluginView::updatePluginWidget() { if (!parent()) return; ASSERT(parent()->isFrameView()); FrameView* frameView = static_cast<FrameView*>(parent()); IntRect oldWindowRect = m_windowRect; IntRect oldClipRect = m_clipRect; m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); m_clipRect = windowClipRect(); m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) return; // in order to move/resize the plugin window at the same time as the rest of frame // during e.g. scrolling, we set the mask and geometry in the paint() function, but // as paint() isn't called when the plugin window is outside the frame which can // be caused by a scroll, we need to move/resize immediately. if (!m_windowRect.intersects(frameView->frameRect())) setNPWindowIfNeeded(); }
void PluginView::updatePluginWidget() { if (!parent()) return; ASSERT(parent()->isFrameView()); FrameView* frameView = static_cast<FrameView*>(parent()); IntRect oldWindowRect = m_windowRect; IntRect oldClipRect = m_clipRect; m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); m_clipRect = windowClipRect(); m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) return; if (!m_isWindowed && m_windowRect.size() != oldWindowRect.size()) { if (m_drawable) XFreePixmap(QX11Info::display(), m_drawable); m_drawable = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), m_windowRect.width(), m_windowRect.height(), ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth); QApplication::syncX(); // make sure that the server knows about the Drawable } // do not call setNPWindowIfNeeded immediately, will be called on paint() m_hasPendingGeometryChange = true; // in order to move/resize the plugin window at the same time as the // rest of frame during e.g. scrolling, we set the window geometry // in the paint() function, but as paint() isn't called when the // plugin window is outside the frame which can be caused by a // scroll, we need to move/resize immediately. if (!m_windowRect.intersects(frameView->frameRect())) setNPWindowIfNeeded(); }
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); } } }