FocusCandidate::FocusCandidate(Node* node, FocusDirection direction) : visibleNode(0) , focusableNode(0) , enclosingScrollableBox(0) , distance(maxDistance()) , parentDistance(maxDistance()) , alignment(None) , parentAlignment(None) , isOffscreen(true) , isOffscreenAfterScrolling(true) { ASSERT(node); ASSERT(node->isElementNode()); if (node->hasTagName(HTMLNames::areaTag)) { HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node); HTMLImageElement* image = area->imageElement(); if (!image || !image->renderer()) return; visibleNode = image; rect = virtualRectForAreaElementAndDirection(area, direction); } else { if (!node->renderer()) return; visibleNode = node; rect = nodeRectInAbsoluteCoordinates(node, true /* ignore border */); } focusableNode = node; isOffscreen = hasOffscreenRect(visibleNode); isOffscreenAfterScrolling = hasOffscreenRect(visibleNode, direction); }
// FIXME: This function does not behave correctly with transformed frames. static IntRect renderRectRelativeToRootDocument(RenderObject* render) { ASSERT(render); IntRect rect(render->absoluteClippedOverflowRect()); if (rect.isEmpty()) { Element* e = static_cast<Element*>(render->node()); rect = e->getRect(); } // In cases when the |render|'s associated node is in a scrollable inner // document, we only consider its scrollOffset if it is not offscreen. Node* node = render->node(); Document* mainDocument = node->document()->page()->mainFrame()->document(); bool considerScrollOffset = !(hasOffscreenRect(node) && node->document() != mainDocument); if (considerScrollOffset) { if (FrameView* frameView = render->node()->document()->view()) rect.move(-frameView->scrollOffset()); } // Handle nested frames. for (Frame* frame = render->document()->frame(); frame; frame = frame->tree()->parent()) { if (HTMLFrameOwnerElement* ownerElement = frame->ownerElement()) rect.move(ownerElement->offsetLeft(), ownerElement->offsetTop()); } return rect; }
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; }