diff options
Diffstat (limited to 'WebCore/page/FocusController.cpp')
-rw-r--r-- | WebCore/page/FocusController.cpp | 66 |
1 files changed, 36 insertions, 30 deletions
diff --git a/WebCore/page/FocusController.cpp b/WebCore/page/FocusController.cpp index 5418c89..9ca18dd 100644 --- a/WebCore/page/FocusController.cpp +++ b/WebCore/page/FocusController.cpp @@ -40,9 +40,10 @@ #include "Frame.h" #include "FrameTree.h" #include "FrameView.h" -#include "HitTestResult.h" -#include "HTMLFrameOwnerElement.h" +#include "HTMLAreaElement.h" +#include "HTMLImageElement.h" #include "HTMLNames.h" +#include "HitTestResult.h" #include "KeyboardEvent.h" #include "Page.h" #include "Range.h" @@ -59,7 +60,6 @@ namespace WebCore { using namespace HTMLNames; using namespace std; -static void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& startingRect, FocusCandidate& candidate, FocusCandidate& closest); static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool focused) { // If we have a focused node we should dispatch blur on it before we blur the window. @@ -130,6 +130,9 @@ void FocusController::setFocused(bool focused) m_isFocused = focused; + if (!m_isFocused) + focusedOrMainFrame()->eventHandler()->stopAutoscrollTimer(); + if (!m_focusedFrame) setFocusedFrame(m_page->mainFrame()); @@ -412,13 +415,13 @@ void FocusController::setActive(bool active) dispatchEventsOnWindowAndFocusedNode(m_focusedFrame->document(), active); } -void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& startingRect, FocusCandidate& candidate, FocusCandidate& closest) +static void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& startingRect, FocusCandidate& candidate, FocusCandidate& closest) { - if (!candidate.node->isElementNode() || !candidate.node->renderer()) + if (!candidate.visibleNode->isElementNode() || !candidate.visibleNode->renderer()) return; // Ignore iframes that don't have a src attribute - if (candidate.node->isFrameOwnerElement() && !static_cast<HTMLFrameOwnerElement*>(candidate.node)->contentFrame()) + if (frameOwnerElement(candidate) && (!frameOwnerElement(candidate)->contentFrame() || candidate.rect.isEmpty())) return; // Ignore off screen child nodes of containers that do not scroll (overflow:hidden) @@ -444,12 +447,12 @@ void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& start // If 2 nodes are intersecting, do hit test to find which node in on top. int x = intersectionRect.x() + intersectionRect.width() / 2; int y = intersectionRect.y() + intersectionRect.height() / 2; - HitTestResult result = candidate.node->document()->page()->mainFrame()->eventHandler()->hitTestResultAtPoint(IntPoint(x, y), false, true); - if (candidate.node->contains(result.innerNode())) { + HitTestResult result = candidate.visibleNode->document()->page()->mainFrame()->eventHandler()->hitTestResultAtPoint(IntPoint(x, y), false, true); + if (candidate.visibleNode->contains(result.innerNode())) { closest = candidate; return; } - if (closest.node->contains(result.innerNode())) + if (closest.visibleNode->contains(result.innerNode())) return; } @@ -473,13 +476,13 @@ void FocusController::findFocusCandidateInContainer(Node* container, const IntRe if (node == focusedNode) continue; - if (!node->renderer()) + if (!node->isKeyboardFocusable(event) && !node->isFrameOwnerElement() && !canScrollInDirection(direction, node)) continue; - if (!node->isKeyboardFocusable(event) && !node->isFrameOwnerElement() && !canScrollInDirection(direction, node)) + FocusCandidate candidate = FocusCandidate(node, direction); + if (candidate.isNull()) continue; - FocusCandidate candidate(node, direction); candidate.enclosingScrollableBox = container; updateFocusCandidateIfNeeded(direction, startingRect, candidate, closest); } @@ -500,23 +503,20 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons findFocusCandidateInContainer(container, newStartingRect, direction, event, focusCandidate); if (focusCandidate.isNull()) { - if (canScrollInDirection(direction, container)) { - // Nothing to focus, scroll if possible. - scrollInDirection(container, direction); - return true; - } - // Return false will cause a re-try, skipping this container. - return false; + // Nothing to focus, scroll if possible. + // NOTE: If no scrolling is performed (i.e. scrollInDirection returns false), the + // spatial navigation algorithm will skip this container. + return scrollInDirection(container, direction); } - if (focusCandidate.node->isFrameOwnerElement()) { - HTMLFrameOwnerElement* frameElement = static_cast<HTMLFrameOwnerElement*>(focusCandidate.node); + + if (HTMLFrameOwnerElement* frameElement = frameOwnerElement(focusCandidate)) { // If we have an iframe without the src attribute, it will not have a contentFrame(). // We ASSERT here to make sure that // updateFocusCandidateIfNeeded() will never consider such an iframe as a candidate. ASSERT(frameElement->contentFrame()); if (focusCandidate.isOffscreenAfterScrolling) { - scrollInDirection(focusCandidate.node->document(), direction); + scrollInDirection(focusCandidate.visibleNode->document(), direction); return true; } // Navigate into a new frame. @@ -527,13 +527,13 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons frameElement->contentFrame()->document()->updateLayoutIgnorePendingStylesheets(); if (!advanceFocusDirectionallyInContainer(frameElement->contentFrame()->document(), rect, direction, event)) { // The new frame had nothing interesting, need to find another candidate. - return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.node, true), direction, event); + return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.visibleNode, true), direction, event); } return true; } - if (canScrollInDirection(direction, focusCandidate.node)) { + if (canScrollInDirection(direction, focusCandidate.visibleNode)) { if (focusCandidate.isOffscreenAfterScrolling) { - scrollInDirection(focusCandidate.node, direction); + scrollInDirection(focusCandidate.visibleNode, direction); return true; } // Navigate into a new scrollable container. @@ -541,7 +541,7 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons Node* focusedNode = focusedOrMainFrame()->document()->focusedNode(); if (focusedNode && !hasOffscreenRect(focusedNode)) startingRect = nodeRectInAbsoluteCoordinates(focusedNode, true); - return advanceFocusDirectionallyInContainer(focusCandidate.node, startingRect, direction, event); + return advanceFocusDirectionallyInContainer(focusCandidate.visibleNode, startingRect, direction, event); } if (focusCandidate.isOffscreenAfterScrolling) { Node* container = focusCandidate.enclosingScrollableBox; @@ -550,7 +550,7 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons } // We found a new focus node, navigate to it. - Element* element = toElement(focusCandidate.node); + Element* element = toElement(focusCandidate.focusableNode); ASSERT(element); element->focus(false); @@ -571,9 +571,15 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa // Figure out the starting rect. IntRect startingRect; - if (focusedNode && !hasOffscreenRect(focusedNode)) { - container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, focusedNode); - startingRect = nodeRectInAbsoluteCoordinates(focusedNode, true /* ignore border */); + if (focusedNode) { + if (!hasOffscreenRect(focusedNode)) { + container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, focusedNode); + startingRect = nodeRectInAbsoluteCoordinates(focusedNode, true /* ignore border */); + } else if (focusedNode->hasTagName(areaTag)) { + HTMLAreaElement* area = static_cast<HTMLAreaElement*>(focusedNode); + container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, area->imageElement()); + startingRect = virtualRectForAreaElementAndDirection(direction, area); + } } bool consumed = false; |