static Node* findLastFocusableNode(Frame* frame, const IntRect* specificRect) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif Node* node = frame->document()->lastChild(); while (node) { if (!isNodeInSpecificRect(node, specificRect)) { node = node->traversePreviousNodePostOrder(); continue; } if (node->isFrameOwnerElement()) { HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node); if (owner->contentFrame()) { node = findLastFocusableNode(owner->contentFrame(), specificRect); if (node) break; node = owner; } } else if (isScrollableContainerNode(node) && !node->renderer()->isTextArea()) { node = node->lastChild(); } if (node->isFocusable() && !node->isFrameOwnerElement()) { break; } node = node->traversePreviousNodePostOrder(); } if (node) { return node->isFocusable() ? node : 0; } return 0; }
NodePrivate::~NodePrivate() { CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); delete m_renderer; if (m_document) delete m_document; if (m_parentElement) delete m_parentElement; if (m_parent) delete m_parent; if (m_parentNode) delete m_parentNode; if (m_firstChild) delete m_firstChild; if (m_traverseNextNode) delete m_traverseNextNode; if (m_traverseNextSibling) delete m_traverseNextSibling; if (m_shadowHost) delete m_shadowHost; if (m_parentNamedNodeMap) delete m_parentNamedNodeMap; if (m_HTMLElement) delete m_HTMLElement; if (m_parentOrShadowHostElement) delete m_parentOrShadowHostElement; if (m_querySelectorElement) delete m_querySelectorElement; }
void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif if (!shouldRepaint(ur)) return; // We always just invalidate the root view, since we could be an iframe that is clipped out // or even invisible. Element* elt = document()->ownerElement(); if (!elt) m_frameView->repaintContentRectangle(ur, immediate); else if (RenderBox* obj = elt->renderBox()) { IntRect vr = viewRect(); IntRect r = intersection(ur, vr); // Subtract out the contentsX and contentsY offsets to get our coords within the viewing // rectangle. r.move(-vr.x(), -vr.y()); // FIXME: Hardcoded offsets here are not good. r.move(obj->borderLeft() + obj->paddingLeft(), obj->borderTop() + obj->paddingTop()); obj->repaintRectangle(r, immediate); } }
void FocusController::findHorizontallyFocusableNodeInRect(FocusDirection direction, Node* start, KeyboardEvent* event, const IntRect* rect, Node** candidateNode, IntRect& candidateNodeRect) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif // ASSERT(direction == FocusDirectionLeft || direction == FocusDirectionRight); if (!start) return ; Node* node = start; HTMLFrameOwnerElement* owner; Document* document; IntRect nodeRect; while (node) { if (!isNodeInSpecificRect(node, rect)) { node = getClosestNode(node, direction); continue; } owner = 0; if (node->isFrameOwnerElement()) { owner = static_cast<HTMLFrameOwnerElement*>(node); if (!owner->contentFrame()) { *candidateNode = 0; return; } document = owner->contentFrame()->document(); findHorizontallyFocusableNodeInRect(direction, document, event, rect, candidateNode, candidateNodeRect); } else if (isScrollableContainerNode(node) && !node->renderer()->isTextArea()) { findHorizontallyFocusableNodeInRect(direction, node->firstChild(), event, rect, candidateNode, candidateNodeRect); } else { if (node->isFocusable() && !node->isFrameOwnerElement()) { nodeRect = node->renderer()->absoluteBoundingBoxRect(); FrameView* frameView = node->document()->view(); if (!frameView) { *candidateNode = 0; return; } nodeRect = frameView->contentsToWindow(nodeRect); nodeRect.intersect(*rect); if (!nodeRect.isEmpty()) { if (candidateNodeRect.isEmpty()) { *candidateNode = node; candidateNodeRect = nodeRect; } if (direction == FocusDirectionRight && candidateNodeRect.x() > nodeRect.x()) { *candidateNode = node; candidateNodeRect = nodeRect; } else if (direction == FocusDirectionLeft && candidateNodeRect.x() < nodeRect.x()) { *candidateNode = node; candidateNodeRect = nodeRect; } } } } node = getClosestNode(node, direction); } }
void RenderView::paint(PaintInfo& paintInfo, int tx, int ty) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif // If we ever require layout but receive a paint anyway, something has gone horribly wrong. ASSERT(!needsLayout()); // Cache the print rect because the dirty rect could get changed during painting. if (printing()) setPrintRect(paintInfo.rect); else setPrintRect(IntRect()); paintObject(paintInfo, tx, ty); }
void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif // Check to see if we are enclosed by a layer that requires complex painting rules. If so, we cannot blit // when scrolling, and we need to use slow repaints. Examples of layers that require this are transparent layers, // layers with reflections, or transformed layers. // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being inside // a transform, transparency layer, etc. Element* elt; for (elt = document()->ownerElement(); view() && elt && elt->renderer(); elt = elt->document()->ownerElement()) { RenderLayer* layer = elt->renderer()->enclosingLayer(); if (layer->requiresSlowRepaints()) { frameView()->setUseSlowRepaints(); break; } } // If painting will entirely fill the view, no need to fill the background. if (elt || rendererObscuresBackground(firstChild()) || !view()) return; // This code typically only executes if the root element's visibility has been set to hidden, // or there is a transform on the <html>. // Only fill with the base background color (typically white) if we're the root document, // since iframes/frames with no background in the child document should show the parent's background. if (view()->isTransparent()) // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent. frameView()->setUseSlowRepaints(); // The parent must show behind the child. else { Color baseColor = frameView()->baseBackgroundColor(); if (baseColor.alpha() > 0) { paintInfo.context->save(); paintInfo.context->setCompositeOperation(CompositeCopy); paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace()); paintInfo.context->restore(); } else paintInfo.context->clearRect(paintInfo.rect); } }
Node* FocusController::findNextFocusableNodeInRect(const FocusDirection direction, Frame* frame, const IntRect* rect) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif ASSERT(frame); ASSERT(rect); Node* start; if (direction == FocusDirectionUp) { Node* last = 0; for (last = frame->document()->lastChild(); last && last->lastChild(); last = last->lastChild()) ; // Empty loop. start = last; } else { ASSERT(direction == FocusDirectionDown || direction == FocusDirectionLeft || direction == FocusDirectionRight); start = frame->document()->firstChild(); } frame->document()->updateLayoutIgnorePendingStylesheets(); Node* node = 0; IntRect candidateNodeRect; switch (direction) { case FocusDirectionUp: case FocusDirectionDown: node = findVerticallyFocusableNodeInRect(direction, start, 0, rect); break; case FocusDirectionRight: case FocusDirectionLeft: findHorizontallyFocusableNodeInRect(direction, start, 0, rect, &node, candidateNodeRect); break; default: node = 0; break; } return node; }
Node* FocusController::findNextFocusableNode(const FocusDirection direction, const IntRect* specificRect) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif Frame* frame = focusedOrMainFrame(); ASSERT(frame); Document* focusedDocument = frame->document(); if (!focusedDocument) return 0; focusedDocument->updateLayoutIgnorePendingStylesheets(); Node* focusedNode = focusedDocument->focusedNode(); if (!focusedNode) { if (direction == FocusDirectionUp) { return findLastFocusableNode(m_page->mainFrame(), specificRect); } else { return findFirstFocusableNode(m_page->mainFrame(), specificRect); } } frame = frame->tree()->top(); FocusCandidate focusCandidate; findFocusableNodeInDirection(frame->document()->firstChild(), focusedNode, direction, 0, focusCandidate, FocusCandidate(), specificRect); Node* node = focusCandidate.node; if (!node || !node->isElementNode()) { return 0; } if (hasOffscreenRect(node)) { return 0; } return node; }
Node* FocusController::findVerticallyFocusableNodeInRect(FocusDirection direction, Node* start, KeyboardEvent* event, const IntRect* rect) { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif ASSERT(direction == FocusDirectionUp || direction == FocusDirectionDown); if (!start) return 0; Node* node = start; HTMLFrameOwnerElement* owner; Document* document; while (node) { if (!isNodeInSpecificRect(node, rect)) { node = getClosestNode(node, direction); continue; } owner = 0; if (node->isFrameOwnerElement()) { owner = static_cast<HTMLFrameOwnerElement*>(node); if (!owner->contentFrame()) { node = 0; break; } document = owner->contentFrame()->document(); if (direction == FocusDirectionUp) { node = findVerticallyFocusableNodeInRect(direction, document->lastChild(), event, rect); } else { node = findVerticallyFocusableNodeInRect(direction, document->firstChild(), event, rect); } if (node) break; node = getClosestNode(owner, direction); continue; } else if (isScrollableContainerNode(node) && !node->renderer()->isTextArea()) { Node* childNode = 0; if (direction == FocusDirectionUp) { childNode = findVerticallyFocusableNodeInRect(direction, node->lastChild(), event, rect); } else { ASSERT(direction == FocusDirectionDown); childNode = findVerticallyFocusableNodeInRect(direction, node->firstChild(), event, rect); } if (!childNode) { node = getClosestNode(node, direction, true); if (!node) break; } else { node = childNode; break; } } if (node->isFocusable() && !node->isFrameOwnerElement()) { break; } if (owner) { node = owner; } node = getClosestNode(node, direction); } return node; }
void FocusController::findFocusableNodeInDirection(Node* outer, Node* focusedNode, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closest, const FocusCandidate& candidateParent) #endif { #if PLATFORM(WKC) CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT); #endif ASSERT(outer); ASSERT(candidateParent.isNull() || candidateParent.node->isFrameOwnerElement() || isScrollableContainerNode(candidateParent.node)); // Walk all the child nodes and update closest if we find a nearer node. Node* node = outer; while (node) { // Inner documents case. if (node->isFrameOwnerElement()) { deepFindFocusableNodeInDirection(node, focusedNode, direction, event, closest, specificRect); // Scrollable block elements (e.g. <div>, etc) case. } else if (isScrollableContainerNode(node) && !node->renderer()->isTextArea()) { deepFindFocusableNodeInDirection(node, focusedNode, direction, event, closest, specificRect); node = node->traverseNextSibling(); continue; #if PLATFORM(WKC) } else if (node != focusedNode && node->isFocusable() && isNodeInSpecificRect(node, specificRect)) { #else } else if (node != focusedNode && node->isKeyboardFocusable(event)) { #endif FocusCandidate candidate(node); // There are two ways to identify we are in a recursive call from deepFindFocusableNodeInDirection // (i.e. processing an element in an iframe, frame or a scrollable block element): // 1) If candidateParent is not null, and it holds the distance and alignment data of the // parent container element itself; // 2) Parent of outer is <frame> or <iframe>; // 3) Parent is any other scrollable block element. if (!candidateParent.isNull()) { candidate.parentAlignment = candidateParent.alignment; candidate.parentDistance = candidateParent.distance; candidate.enclosingScrollableBox = candidateParent.node; } else if (!isInRootDocument(outer)) { #if PLATFORM(WKC) if (outer->parent() && outer->parent()->isDocumentNode()) { Document* document = static_cast<Document*>(outer->parent()); candidate.enclosingScrollableBox = static_cast<Node*>(document->ownerElement()); } #else if (Document* document = static_cast<Document*>(outer->parent())) candidate.enclosingScrollableBox = static_cast<Node*>(document->ownerElement()); #endif } else if (isScrollableContainerNode(outer->parent())) candidate.enclosingScrollableBox = outer->parent(); // Get distance and alignment from current candidate. distanceDataForNode(direction, focusedNode, candidate); // Bail out if distance is maximum. if (candidate.distance == maxDistance()) { node = node->traverseNextNode(outer->parent()); continue; } updateFocusCandidateIfCloser(focusedNode, candidate, closest); } node = node->traverseNextNode(outer->parent()); } }