void Internals::setBackgroundBlurOnNode(Node* node, int blurLength, ExceptionCode& ec) { if (!node) { ec = INVALID_ACCESS_ERR; return; } RenderObject* renderObject = node->renderer(); if (!renderObject) { ec = INVALID_NODE_TYPE_ERR; return; } RenderLayer* renderLayer = renderObject->enclosingLayer(); if (!renderLayer || !renderLayer->isComposited()) { ec = INVALID_STATE_ERR; return; } GraphicsLayer* graphicsLayer = renderLayer->backing()->graphicsLayer(); if (!graphicsLayer) { ec = INVALID_NODE_TYPE_ERR; return; } PlatformLayer* platformLayer = graphicsLayer->platformLayer(); if (!platformLayer) { ec = INVALID_NODE_TYPE_ERR; return; } FilterOperations filters; filters.operations().append(BlurFilterOperation::create(Length(blurLength, Fixed), FilterOperation::BLUR)); platformLayer->setBackgroundFilters(filters); }
RenderLayer* LinkHighlight::computeEnclosingCompositingLayer() { if (!m_node || !m_node->renderer()) return 0; // Find the nearest enclosing composited layer and attach to it. We may need to cross frame boundaries // to find a suitable layer. RenderObject* renderer = m_node->renderer(); RenderLayer* renderLayer; do { renderLayer = renderer->enclosingLayer()->enclosingCompositingLayerForRepaint(); if (!renderLayer) { renderer = renderer->frame()->ownerRenderer(); if (!renderer) return 0; } } while (!renderLayer); CompositedLayerMappingPtr compositedLayerMapping = renderLayer->compositingState() == PaintsIntoGroupedBacking ? renderLayer->groupedMapping() : renderLayer->compositedLayerMapping(); GraphicsLayer* newGraphicsLayer = renderLayer->compositingState() == PaintsIntoGroupedBacking ? compositedLayerMapping->squashingLayer() : compositedLayerMapping->mainGraphicsLayer(); m_clipLayer->setTransform(SkMatrix44(SkMatrix44::kIdentity_Constructor)); if (!newGraphicsLayer->drawsContent()) { if (renderLayer->scrollableArea() && renderLayer->scrollableArea()->usesCompositedScrolling()) { ASSERT(renderLayer->hasCompositedLayerMapping() && renderLayer->compositedLayerMapping()->scrollingContentsLayer()); newGraphicsLayer = compositedLayerMapping->scrollingContentsLayer(); } } if (m_currentGraphicsLayer != newGraphicsLayer) { if (m_currentGraphicsLayer) clearGraphicsLayerLinkHighlightPointer(); m_currentGraphicsLayer = newGraphicsLayer; m_currentGraphicsLayer->addLinkHighlight(this); } return renderLayer; }
QT_END_NAMESPACE static bool webframe_scrollOverflow(WebCore::Frame* frame, int dx, int dy, const QPoint& pos) { if (!frame || !frame->document() || !frame->view() || !frame->eventHandler()) return false; QPoint contentsPos = frame->view()->windowToContents(pos); Node* node = frame->document()->elementFromPoint(contentsPos.x(), contentsPos.y()); if (!node) return false; RenderObject* renderer = node->renderer(); if (!renderer) return false; if (renderer->isListBox()) return false; RenderLayer* renderLayer = renderer->enclosingLayer(); if (!renderLayer) return false; bool scrolledHorizontal = false; bool scrolledVertical = false; if (dx > 0) scrolledHorizontal = renderLayer->scroll(ScrollRight, ScrollByPixel, dx); else if (dx < 0) scrolledHorizontal = renderLayer->scroll(ScrollLeft, ScrollByPixel, qAbs(dx)); if (dy > 0) scrolledVertical = renderLayer->scroll(ScrollDown, ScrollByPixel, dy); else if (dy < 0) scrolledVertical = renderLayer->scroll(ScrollUp, ScrollByPixel, qAbs(dy)); return (scrolledHorizontal || scrolledVertical); }
static bool webframe_scrollOverflow(WebCore::Frame* frame, int dx, int dy) { if (!frame || !frame->document() || !frame->eventHandler()) return false; Node* node = frame->document()->focusedNode(); if (!node) node = frame->document()->elementFromPoint(frame->eventHandler()->currentMousePosition().x(), frame->eventHandler()->currentMousePosition().y()); if (!node) return false; RenderObject* renderer = node->renderer(); if (!renderer) return false; if (renderer->isListBox()) return false; RenderLayer* renderLayer = renderer->enclosingLayer(); if (!renderLayer) return false; bool scrolledHorizontal = false; bool scrolledVertical = false; if (dx > 0) scrolledHorizontal = renderLayer->scroll(ScrollRight, ScrollByPixel, dx); else if (dx < 0) scrolledHorizontal = renderLayer->scroll(ScrollLeft, ScrollByPixel, qAbs(dx)); if (dy > 0) scrolledVertical = renderLayer->scroll(ScrollDown, ScrollByPixel, dy); else if (dy < 0) scrolledVertical = renderLayer->scroll(ScrollUp, ScrollByPixel, qAbs(dy)); return (scrolledHorizontal || scrolledVertical); }
void TouchEventHandler::drawTapHighlight() { Element* elementUnderFatFinger = m_lastFatFingersResult.nodeAsElementIfApplicable(); if (!elementUnderFatFinger) return; Element* element = elementForTapHighlight(elementUnderFatFinger); if (!element) return; // Get the element bounding rect in transformed coordinates so we can extract // the focus ring relative position each rect. RenderObject* renderer = element->renderer(); ASSERT(renderer); Frame* elementFrame = element->document()->frame(); ASSERT(elementFrame); FrameView* elementFrameView = elementFrame->view(); if (!elementFrameView) return; // Tell the client if the element is either in a scrollable container or in a fixed positioned container. // On the client side, this info is being used to hide the tap highlight window on scroll. RenderLayer* layer = m_webPage->enclosingFixedPositionedAncestorOrSelfIfFixedPositioned(renderer->enclosingLayer()); bool shouldHideTapHighlightRightAfterScrolling = !layer->renderer()->isRenderView(); shouldHideTapHighlightRightAfterScrolling |= !!m_webPage->m_inRegionScrollStartingNode.get(); IntPoint framePos(m_webPage->frameOffset(elementFrame)); // FIXME: We can get more precise on the <map> case by calculating the rect with HTMLAreaElement::computeRect(). IntRect absoluteRect = renderer->absoluteClippedOverflowRect(); absoluteRect.move(framePos.x(), framePos.y()); IntRect clippingRect; if (elementFrame == m_webPage->mainFrame()) clippingRect = IntRect(IntPoint(0, 0), elementFrameView->contentsSize()); else clippingRect = m_webPage->mainFrame()->view()->windowToContents(m_webPage->getRecursiveVisibleWindowRect(elementFrameView, true /*noClipToMainFrame*/)); clippingRect = intersection(absoluteRect, clippingRect); Vector<FloatQuad> focusRingQuads; renderer->absoluteFocusRingQuads(focusRingQuads); Platform::IntRectRegion region; for (size_t i = 0; i < focusRingQuads.size(); ++i) { IntRect rect = focusRingQuads[i].enclosingBoundingBox(); rect.move(framePos.x(), framePos.y()); IntRect clippedRect = intersection(clippingRect, rect); clippedRect.inflate(2); region = unionRegions(region, Platform::IntRect(clippedRect)); } Color highlightColor = element->renderStyle()->tapHighlightColor(); m_webPage->m_client->drawTapHighlight(region, highlightColor.red(), highlightColor.green(), highlightColor.blue(), highlightColor.alpha(), shouldHideTapHighlightRightAfterScrolling); }
void FrameView::layout(bool allowSubtree) { // We should never layout a Document which is not in a LocalFrame. ASSERT(m_frame); ASSERT(m_frame->view() == this); ScriptForbiddenScope forbidScript; if (isInPerformLayout() || !m_frame->document()->isActive()) return; TRACE_EVENT0("blink", "FrameView::layout"); TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "Layout"); // Protect the view from being deleted during layout (in recalcStyle) RefPtr<FrameView> protector(this); m_hasPendingLayout = false; RELEASE_ASSERT(!isPainting()); if (!allowSubtree && isSubtreeLayout()) { m_layoutSubtreeRoot->markContainingBlocksForLayout(false); m_layoutSubtreeRoot = 0; } performPreLayoutTasks(); // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, // so there's no point to continuing to layout if (protector->hasOneRef()) return; Document* document = m_frame->document(); bool inSubtreeLayout = isSubtreeLayout(); RenderObject* rootForThisLayout = inSubtreeLayout ? m_layoutSubtreeRoot : document->renderView(); if (!rootForThisLayout) { // FIXME: Do we need to set m_size here? ASSERT_NOT_REACHED(); return; } FontCachePurgePreventer fontCachePurgePreventer; RenderLayer* layer; { TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false); m_nestedLayoutCount++; if (!inSubtreeLayout) { if (m_firstLayout) { m_firstLayout = false; m_lastViewportSize = layoutSize(); } m_size = LayoutSize(layoutSize()); } layer = rootForThisLayout->enclosingLayer(); performLayout(rootForThisLayout, inSubtreeLayout); m_layoutSubtreeRoot = 0; } // Reset m_layoutSchedulingEnabled to its previous value. layer->updateLayerPositionsAfterLayout(); m_layoutCount++; ASSERT(!rootForThisLayout->needsLayout()); scheduleOrPerformPostLayoutTasks(); m_nestedLayoutCount--; if (m_nestedLayoutCount) return; #if ENABLE(ASSERT) // Post-layout assert that nobody was re-marked as needing layout during layout. document->renderView()->assertSubtreeIsLaidOut(); #endif }
void FrameView::layout(bool allowSubtree) { if (d->m_midLayout) return; d->m_layoutTimer.stop(); d->m_delayedLayout = false; // Protect the view from being deleted during layout (in recalcStyle) RefPtr<FrameView> protector(this); if (!m_frame) { // FIXME: Do we need to set m_size.width here? // FIXME: Should we set m_size.height here too? m_size.setWidth(visibleWidth()); return; } // we shouldn't enter layout() while painting ASSERT(!m_frame->isPainting()); if (m_frame->isPainting()) return; if (!allowSubtree && d->m_layoutRoot) { d->m_layoutRoot->markContainingBlocksForLayout(false); d->m_layoutRoot = 0; } ASSERT(m_frame->view() == this); // This early return should be removed when rdar://5598072 is resolved. In the meantime, there is a // gigantic CrashTracer because of this issue, and the early return will hopefully cause graceful // failure instead. if (m_frame->view() != this) return; Document* document = m_frame->document(); if (!document) { // FIXME: Should we set m_size.height here too? m_size.setWidth(visibleWidth()); return; } d->m_layoutSchedulingEnabled = false; if (!d->m_nestedLayoutCount && d->m_postLayoutTasksTimer.isActive()) { // This is a new top-level layout. If there are any remaining tasks from the previous // layout, finish them now. d->m_postLayoutTasksTimer.stop(); performPostLayoutTasks(); } // Viewport-dependent media queries may cause us to need completely different style information. // Check that here. if (document->styleSelector()->affectedByViewportChange()) document->updateStyleSelector(); // Always ensure our style info is up-to-date. This can happen in situations where // the layout beats any sort of style recalc update that needs to occur. if (m_frame->needsReapplyStyles()) m_frame->reapplyStyles(); else if (document->hasChangedChild()) document->recalcStyle(); bool subtree = d->m_layoutRoot; // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, // so there's no point to continuing to layout if (protector->hasOneRef()) return; RenderObject* root = subtree ? d->m_layoutRoot : document->renderer(); if (!root) { // FIXME: Do we need to set m_size here? d->m_layoutSchedulingEnabled = true; return; } d->m_nestedLayoutCount++; ScrollbarMode hMode = d->m_hmode; ScrollbarMode vMode = d->m_vmode; if (!subtree) { RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0; if (document->isHTMLDocument()) { Node* body = static_cast<HTMLDocument*>(document)->body(); if (body && body->renderer()) { if (body->hasTagName(framesetTag)) { body->renderer()->setChildNeedsLayout(true); vMode = ScrollbarAlwaysOff; hMode = ScrollbarAlwaysOff; } else if (body->hasTagName(bodyTag)) { if (!d->m_firstLayout && m_size.height() != visibleHeight() && static_cast<RenderBox*>(body->renderer())->stretchesToViewHeight()) body->renderer()->setChildNeedsLayout(true); // It's sufficient to just check the X overflow, // since it's illegal to have visible in only one direction. RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE ? body->renderer() : rootRenderer; applyOverflowToViewport(o, hMode, vMode); // Only applies to HTML UAs, not to XML/XHTML UAs } } } else if (rootRenderer) applyOverflowToViewport(rootRenderer, hMode, vMode); // XML/XHTML UAs use the root element. #ifdef INSTRUMENT_LAYOUT_SCHEDULING if (d->m_firstLayout && !document->ownerElement()) OWB_PRINTF("Elapsed time before first layout: %d\n", document->elapsedTime()); #endif } d->m_doFullRepaint = !subtree && (d->m_firstLayout || static_cast<RenderView*>(root)->printing()); if (!subtree) { // Now set our scrollbar state for the layout. ScrollbarMode currentHMode = hScrollbarMode(); ScrollbarMode currentVMode = vScrollbarMode(); if (d->m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { suppressScrollbars(true); if (d->m_firstLayout) { d->m_firstLayout = false; d->m_firstLayoutCallbackPending = true; d->m_lastLayoutSize = IntSize(width(), height()); d->m_lastZoomFactor = root->style()->zoom(); // Set the initial vMode to AlwaysOn if we're auto. if (vMode == ScrollbarAuto) ScrollView::setVScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear. // Set the initial hMode to AlwaysOff if we're auto. if (hMode == ScrollbarAuto) ScrollView::setHScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear. } if (hMode == vMode) ScrollView::setScrollbarsMode(hMode); else { ScrollView::setHScrollbarMode(hMode); ScrollView::setVScrollbarMode(vMode); } suppressScrollbars(false, true); } IntSize oldSize = m_size; m_size = IntSize(visibleWidth(), visibleHeight()); if (oldSize != m_size) d->m_doFullRepaint = true; } RenderLayer* layer = root->enclosingLayer(); pauseScheduledEvents(); if (subtree) root->view()->pushLayoutState(root); d->m_midLayout = true; beginDeferredRepaints(); root->layout(); endDeferredRepaints(); d->m_midLayout = false; if (subtree) root->view()->popLayoutState(); d->m_layoutRoot = 0; m_frame->invalidateSelection(); d->m_layoutSchedulingEnabled = true; if (!subtree && !static_cast<RenderView*>(root)->printing()) adjustViewSize(); // Now update the positions of all layers. beginDeferredRepaints(); layer->updateLayerPositions(d->m_doFullRepaint); endDeferredRepaints(); d->m_layoutCount++; #if PLATFORM(MAC) if (AXObjectCache::accessibilityEnabled()) root->document()->axObjectCache()->postNotificationToElement(root, "AXLayoutComplete"); #endif #if ENABLE(DASHBOARD_SUPPORT) updateDashboardRegions(); #endif ASSERT(!root->needsLayout()); setStaticBackground(useSlowRepaints()); if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) updateOverflowStatus(visibleWidth() < contentsWidth(), visibleHeight() < contentsHeight()); if (!d->m_postLayoutTasksTimer.isActive()) { // Calls resumeScheduledEvents() performPostLayoutTasks(); if (needsLayout()) { // Post-layout widget updates or an event handler made us need layout again. // Lay out again, but this time defer widget updates and event dispatch until after // we return. d->m_postLayoutTasksTimer.startOneShot(0); pauseScheduledEvents(); layout(); } } else { resumeScheduledEvents(); ASSERT(d->m_enqueueEvents); } d->m_nestedLayoutCount--; }