diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
| commit | a4e969f4965059196ca948db781e52f7cfebf19e (patch) | |
| tree | 6ca352808c8fdc52006a0f33f6ae3c593b23867d /Source/WebCore/page/FocusController.cpp | |
| parent | 41386e9cb918eed93b3f13648cbef387e371e451 (diff) | |
| download | WebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz | |
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Source/WebCore/page/FocusController.cpp')
| -rw-r--r-- | Source/WebCore/page/FocusController.cpp | 274 |
1 files changed, 178 insertions, 96 deletions
diff --git a/Source/WebCore/page/FocusController.cpp b/Source/WebCore/page/FocusController.cpp index a52b0d720..6459cf1bb 100644 --- a/Source/WebCore/page/FocusController.cpp +++ b/Source/WebCore/page/FocusController.cpp @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -45,11 +45,11 @@ #include "HTMLImageElement.h" #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "HTMLPlugInElement.h" #include "HTMLTextAreaElement.h" #include "HitTestResult.h" #include "KeyboardEvent.h" #include "MainFrame.h" -#include "NodeRenderingTraversal.h" #include "Page.h" #include "Range.h" #include "RenderWidget.h" @@ -60,12 +60,64 @@ #include "Widget.h" #include "htmlediting.h" // For firstPositionInOrBeforeNode #include <limits> +#include <wtf/CurrentTime.h> #include <wtf/Ref.h> namespace WebCore { using namespace HTMLNames; +// FIXME: Focus navigation should work with shadow trees that have slots. +static Node* firstChildInScope(const Node* node) +{ + ASSERT(node); + if (node->shadowRoot()) + return nullptr; + return node->firstChild(); +} + +static Node* lastChildInScope(const Node* node) +{ + ASSERT(node); + if (node->shadowRoot()) + return nullptr; + return node->lastChild(); +} + +static Node* parentInScope(const Node* node) +{ + if (node->isShadowRoot()) + return nullptr; + + ContainerNode* parent = node->parentNode(); + if (parent && parent->shadowRoot()) + return nullptr; + + return parent; +} + +static Node* nextInScope(const Node* node) +{ + if (Node* next = firstChildInScope(node)) + return next; + if (Node* next = node->nextSibling()) + return next; + const Node* current = node; + while (current && !current->nextSibling()) + current = parentInScope(current); + return current ? current->nextSibling() : nullptr; +} + +static Node* previousInScope(const Node* node) +{ + if (Node* current = node->previousSibling()) { + while (Node* child = lastChildInScope(current)) + current = child; + return current; + } + return parentInScope(node); +} + FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope) : m_rootTreeScope(treeScope) { @@ -74,24 +126,24 @@ FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope) ContainerNode* FocusNavigationScope::rootNode() const { - return m_rootTreeScope->rootNode(); + return &m_rootTreeScope->rootNode(); } Element* FocusNavigationScope::owner() const { ContainerNode* root = rootNode(); - if (root->isShadowRoot()) - return toShadowRoot(root)->hostElement(); + if (is<ShadowRoot>(*root)) + return downcast<ShadowRoot>(*root).host(); if (Frame* frame = root->document().frame()) return frame->ownerElement(); - return 0; + return nullptr; } FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(Node* node) { ASSERT(node); Node* root = node; - for (Node* n = node; n; n = NodeRenderingTraversal::parentInScope(n)) + for (Node* n = node; n; n = parentInScope(n)) root = n; // The result is not always a ShadowRoot nor a DocumentNode since // a starting node is in an orphaned tree in composed shadow tree. @@ -101,8 +153,8 @@ FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(Node* node) FocusNavigationScope FocusNavigationScope::focusNavigationScopeOwnedByShadowHost(Node* node) { ASSERT(node); - ASSERT(toElement(node)->shadowRoot()); - return FocusNavigationScope(toElement(node)->shadowRoot()); + ASSERT(downcast<Element>(*node).shadowRoot()); + return FocusNavigationScope(downcast<Element>(*node).shadowRoot()); } FocusNavigationScope FocusNavigationScope::focusNavigationScopeOwnedByIFrame(HTMLFrameOwnerElement* frame) @@ -125,15 +177,15 @@ static inline void dispatchEventsOnWindowAndFocusedElement(Document* document, b } if (!focused && document->focusedElement()) - document->focusedElement()->dispatchBlurEvent(0); + document->focusedElement()->dispatchBlurEvent(nullptr); document->dispatchWindowEvent(Event::create(focused ? eventNames().focusEvent : eventNames().blurEvent, false, false)); if (focused && document->focusedElement()) - document->focusedElement()->dispatchFocusEvent(0, FocusDirectionNone); + document->focusedElement()->dispatchFocusEvent(nullptr, FocusDirectionNone); } static inline bool hasCustomFocusLogic(Element& element) { - return element.isHTMLElement() && toHTMLElement(element).hasCustomFocusLogic(); + return is<HTMLElement>(element) && downcast<HTMLElement>(element).hasCustomFocusLogic(); } static inline bool isNonFocusableShadowHost(Element& element, KeyboardEvent& event) @@ -143,14 +195,14 @@ static inline bool isNonFocusableShadowHost(Element& element, KeyboardEvent& eve static inline bool isFocusableShadowHost(Node& node, KeyboardEvent& event) { - return node.isElementNode() && toElement(node).isKeyboardFocusable(&event) && toElement(node).shadowRoot() && !hasCustomFocusLogic(toElement(node)); + return is<Element>(node) && downcast<Element>(node).isKeyboardFocusable(&event) && downcast<Element>(node).shadowRoot() && !hasCustomFocusLogic(downcast<Element>(node)); } static inline int adjustedTabIndex(Node& node, KeyboardEvent& event) { - if (!node.isElementNode()) + if (!is<Element>(node)) return 0; - return isNonFocusableShadowHost(toElement(node), event) ? 0 : toElement(node).tabIndex(); + return isNonFocusableShadowHost(downcast<Element>(node), event) ? 0 : downcast<Element>(node).tabIndex(); } static inline bool shouldVisit(Element& element, KeyboardEvent& event) @@ -158,12 +210,11 @@ static inline bool shouldVisit(Element& element, KeyboardEvent& event) return element.isKeyboardFocusable(&event) || isNonFocusableShadowHost(element, event); } -FocusController::FocusController(Page& page) +FocusController::FocusController(Page& page, ViewState::Flags viewState) : m_page(page) - , m_isActive(false) - , m_isFocused(false) , m_isChangingFocusedFrame(false) - , m_contentIsVisible(false) + , m_viewState(viewState) + , m_focusRepaintTimer(*this, &FocusController::focusRepaintTimerFired) { } @@ -205,12 +256,12 @@ Frame& FocusController::focusedOrMainFrame() const void FocusController::setFocused(bool focused) { - if (isFocused() == focused) - return; - - m_isFocused = focused; + m_page.setViewState(focused ? m_viewState | ViewState::IsFocused : m_viewState & ~ViewState::IsFocused); +} - if (!m_isFocused) +void FocusController::setFocusedInternal(bool focused) +{ + if (!isFocused()) focusedOrMainFrame().eventHandler().stopAutoscrollTimer(); if (!m_focusedFrame) @@ -227,8 +278,8 @@ Element* FocusController::findFocusableElementDescendingDownIntoFrameDocument(Fo // The node we found might be a HTMLFrameOwnerElement, so descend down the tree until we find either: // 1) a focusable node, or // 2) the deepest-nested HTMLFrameOwnerElement. - while (element && element->isFrameOwnerElement()) { - HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*element); + while (is<HTMLFrameOwnerElement>(element)) { + HTMLFrameOwnerElement& owner = downcast<HTMLFrameOwnerElement>(*element); if (!owner.contentFrame()) break; Element* foundElement = findFocusableElement(direction, FocusNavigationScope::focusNavigationScopeOwnedByIFrame(&owner), 0, event); @@ -281,7 +332,7 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, Keyb bool caretBrowsing = frame.settings().caretBrowsingEnabled(); if (caretBrowsing && !currentNode) - currentNode = frame.selection().start().deprecatedNode(); + currentNode = frame.selection().selection().start().deprecatedNode(); document->updateLayoutIgnorePendingStylesheets(); @@ -290,8 +341,8 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, Keyb if (!element) { // We didn't find a node to focus, so we should try to pass focus to Chrome. if (!initialFocus && m_page.chrome().canTakeFocus(direction)) { - document->setFocusedElement(0); - setFocusedFrame(0); + document->setFocusedElement(nullptr); + setFocusedFrame(nullptr); m_page.chrome().takeFocus(direction); return true; } @@ -311,10 +362,10 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, Keyb return true; } - if (element->isFrameOwnerElement() && (!element->isPluginElement() || !element->isKeyboardFocusable(event))) { + if (is<HTMLFrameOwnerElement>(*element) && (!is<HTMLPlugInElement>(*element) || !element->isKeyboardFocusable(event))) { // We focus frames rather than frame owners. // FIXME: We should not focus frames that have no scrollbars, as focusing them isn't useful to the user. - HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*element); + HTMLFrameOwnerElement& owner = downcast<HTMLFrameOwnerElement>(*element); if (!owner.contentFrame()) return false; @@ -339,8 +390,10 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, Keyb if (caretBrowsing) { Position position = firstPositionInOrBeforeNode(element.get()); VisibleSelection newSelection(position, position, DOWNSTREAM); - if (frame.selection().shouldChangeSelection(newSelection)) - frame.selection().setSelection(newSelection); + if (frame.selection().shouldChangeSelection(newSelection)) { + AXTextStateChangeIntent intent(AXTextStateChangeTypeSelectionMove, AXTextSelection { AXTextSelectionDirectionDiscontiguous, AXTextSelectionGranularityUnknown, true }); + frame.selection().setSelection(newSelection, FrameSelection::defaultSetSelectionOptions(UserTriggered), intent); + } } element->focus(false, direction); @@ -349,7 +402,7 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, Keyb Element* FocusController::findFocusableElementAcrossFocusScope(FocusDirection direction, FocusNavigationScope scope, Node* currentNode, KeyboardEvent* event) { - ASSERT(!currentNode || !currentNode->isElementNode() || !isNonFocusableShadowHost(*toElement(currentNode), *event)); + ASSERT(!is<Element>(currentNode) || !isNonFocusableShadowHost(*downcast<Element>(currentNode), *event)); Element* found; if (currentNode && direction == FocusDirectionForward && isFocusableShadowHost(*currentNode, *event)) { Element* foundInInnerFocusScope = findFocusableElementRecursively(direction, FocusNavigationScope::focusNavigationScopeOwnedByShadowHost(currentNode), 0, event); @@ -407,11 +460,10 @@ Element* FocusController::findFocusableElement(FocusDirection direction, FocusNa Element* FocusController::findElementWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event, FocusDirection direction) { // Search is inclusive of start - using namespace NodeRenderingTraversal; for (Node* node = start; node; node = direction == FocusDirectionForward ? nextInScope(node) : previousInScope(node)) { - if (!node->isElementNode()) + if (!is<Element>(*node)) continue; - Element& element = toElement(*node); + Element& element = downcast<Element>(*node); if (shouldVisit(element, *event) && adjustedTabIndex(element, *event) == tabIndex) return &element; } @@ -423,10 +475,10 @@ static Element* nextElementWithGreaterTabIndex(Node* start, int tabIndex, Keyboa // Search is inclusive of start int winningTabIndex = std::numeric_limits<short>::max() + 1; Element* winner = nullptr; - for (Node* node = start; node; node = NodeRenderingTraversal::nextInScope(node)) { - if (!node->isElementNode()) + for (Node* node = start; node; node = nextInScope(node)) { + if (!is<Element>(*node)) continue; - Element& element = toElement(*node); + Element& element = downcast<Element>(*node); if (shouldVisit(element, event) && element.tabIndex() > tabIndex && element.tabIndex() < winningTabIndex) { winner = &element; winningTabIndex = element.tabIndex(); @@ -441,10 +493,10 @@ static Element* previousElementWithLowerTabIndex(Node* start, int tabIndex, Keyb // Search is inclusive of start int winningTabIndex = 0; Element* winner = nullptr; - for (Node* node = start; node; node = NodeRenderingTraversal::previousInScope(node)) { - if (!node->isElementNode()) + for (Node* node = start; node; node = previousInScope(node)) { + if (!is<Element>(*node)) continue; - Element& element = toElement(*node); + Element& element = downcast<Element>(*node); int currentTabIndex = adjustedTabIndex(element, event); if ((shouldVisit(element, event) || isNonFocusableShadowHost(element, event)) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) { winner = &element; @@ -456,16 +508,14 @@ static Element* previousElementWithLowerTabIndex(Node* start, int tabIndex, Keyb Element* FocusController::nextFocusableElement(FocusNavigationScope scope, Node* start, KeyboardEvent* event) { - using namespace NodeRenderingTraversal; - if (start) { int tabIndex = adjustedTabIndex(*start, *event); // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order if (tabIndex < 0) { for (Node* node = nextInScope(start); node; node = nextInScope(node)) { - if (!node->isElementNode()) + if (!is<Element>(*node)) continue; - Element& element = toElement(*node); + Element& element = downcast<Element>(*node); if (shouldVisit(element, *event) && adjustedTabIndex(element, *event) >= 0) return &element; } @@ -493,8 +543,6 @@ Element* FocusController::nextFocusableElement(FocusNavigationScope scope, Node* Element* FocusController::previousFocusableElement(FocusNavigationScope scope, Node* start, KeyboardEvent* event) { - using namespace NodeRenderingTraversal; - Node* last = nullptr; for (Node* node = scope.rootNode(); node; node = lastChildInScope(node)) last = node; @@ -515,9 +563,9 @@ Element* FocusController::previousFocusableElement(FocusNavigationScope scope, N // However, if a node is excluded from the normal tabbing cycle, the previous focusable node is determined by tree order if (startingTabIndex < 0) { for (Node* node = startingNode; node; node = previousInScope(node)) { - if (!node->isElementNode()) + if (!is<Element>(*node)) continue; - Element& element = toElement(*node); + Element& element = downcast<Element>(*node); if (shouldVisit(element, *event) && adjustedTabIndex(element, *event) >= 0) return &element; } @@ -543,7 +591,7 @@ static bool relinquishesEditingFocus(Node *node) if (!frame || !root) return false; - return frame->editor().shouldEndEditing(rangeOfContents(*root).get()); + return frame->editor().shouldEndEditing(rangeOfContents(*root).ptr()); } static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFrame, Node* newFocusedNode) @@ -553,8 +601,8 @@ static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFram if (oldFocusedFrame->document() != newFocusedFrame->document()) return; - - FrameSelection& selection = oldFocusedFrame->selection(); + + const VisibleSelection& selection = oldFocusedFrame->selection().selection(); if (selection.isNone()) return; @@ -562,7 +610,7 @@ static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFram if (caretBrowsing) return; - Node* selectionStartNode = selection.selection().start().deprecatedNode(); + Node* selectionStartNode = selection.start().deprecatedNode(); if (selectionStartNode == newFocusedNode || selectionStartNode->isDescendantOf(newFocusedNode) || selectionStartNode->deprecatedShadowAncestorNode() == newFocusedNode) return; @@ -574,21 +622,21 @@ static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFram return; if (Node* shadowAncestorNode = root->deprecatedShadowAncestorNode()) { - if (!isHTMLInputElement(shadowAncestorNode) && !isHTMLTextAreaElement(shadowAncestorNode)) + if (!is<HTMLInputElement>(*shadowAncestorNode) && !is<HTMLTextAreaElement>(*shadowAncestorNode)) return; } } } - - selection.clear(); + + oldFocusedFrame->selection().clear(); } bool FocusController::setFocusedElement(Element* element, PassRefPtr<Frame> newFocusedFrame, FocusDirection direction) { RefPtr<Frame> oldFocusedFrame = focusedFrame(); - RefPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0; + RefPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : nullptr; - Element* oldFocusedElement = oldDocument ? oldDocument->focusedElement() : 0; + Element* oldFocusedElement = oldDocument ? oldDocument->focusedElement() : nullptr; if (oldFocusedElement == element) return true; @@ -596,29 +644,29 @@ bool FocusController::setFocusedElement(Element* element, PassRefPtr<Frame> newF if (oldFocusedElement && oldFocusedElement->isRootEditableElement() && !relinquishesEditingFocus(oldFocusedElement)) return false; - m_page.editorClient()->willSetInputMethodState(); + m_page.editorClient().willSetInputMethodState(); clearSelectionIfNeeded(oldFocusedFrame.get(), newFocusedFrame.get(), element); if (!element) { if (oldDocument) - oldDocument->setFocusedElement(0); - m_page.editorClient()->setInputMethodState(false); + oldDocument->setFocusedElement(nullptr); + m_page.editorClient().setInputMethodState(false); return true; } Ref<Document> newDocument(element->document()); if (newDocument->focusedElement() == element) { - m_page.editorClient()->setInputMethodState(element->shouldUseInputMethod()); + m_page.editorClient().setInputMethodState(element->shouldUseInputMethod()); return true; } - if (oldDocument && oldDocument != &newDocument.get()) - oldDocument->setFocusedElement(0); + if (oldDocument && oldDocument != newDocument.ptr()) + oldDocument->setFocusedElement(nullptr); if (newFocusedFrame && !newFocusedFrame->page()) { - setFocusedFrame(0); + setFocusedFrame(nullptr); return false; } setFocusedFrame(newFocusedFrame); @@ -630,18 +678,35 @@ bool FocusController::setFocusedElement(Element* element, PassRefPtr<Frame> newF return false; if (newDocument->focusedElement() == element) - m_page.editorClient()->setInputMethodState(element->shouldUseInputMethod()); + m_page.editorClient().setInputMethodState(element->shouldUseInputMethod()); + + m_focusSetTime = monotonicallyIncreasingTime(); + m_focusRepaintTimer.stop(); return true; } -void FocusController::setActive(bool active) +void FocusController::setViewState(ViewState::Flags viewState) { - if (m_isActive == active) - return; + ViewState::Flags changed = m_viewState ^ viewState; + m_viewState = viewState; + + if (changed & ViewState::IsFocused) + setFocusedInternal(viewState & ViewState::IsFocused); + if (changed & ViewState::WindowIsActive) { + setActiveInternal(viewState & ViewState::WindowIsActive); + if (changed & ViewState::IsVisible) + setIsVisibleAndActiveInternal(viewState & ViewState::WindowIsActive); + } +} - m_isActive = active; +void FocusController::setActive(bool active) +{ + m_page.setViewState(active ? m_viewState | ViewState::WindowIsActive : m_viewState & ~ViewState::WindowIsActive); +} +void FocusController::setActiveInternal(bool active) +{ if (FrameView* view = m_page.mainFrame().view()) { if (!view->platformWidget()) { view->updateLayoutAndStyleIfNeededRecursive(); @@ -663,13 +728,8 @@ static void contentAreaDidShowOrHide(ScrollableArea* scrollableArea, bool didSho scrollableArea->contentAreaDidHide(); } -void FocusController::setContentIsVisible(bool contentIsVisible) +void FocusController::setIsVisibleAndActiveInternal(bool contentIsVisible) { - if (m_contentIsVisible == contentIsVisible) - return; - - m_contentIsVisible = contentIsVisible; - FrameView* view = m_page.mainFrame().view(); if (!view) return; @@ -685,8 +745,7 @@ void FocusController::setContentIsVisible(bool contentIsVisible) if (!scrollableAreas) continue; - for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) { - ScrollableArea* scrollableArea = *it; + for (auto& scrollableArea : *scrollableAreas) { ASSERT(scrollableArea->scrollbarsCanBeActive() || m_page.shouldSuppressScrollbarAnimations()); contentAreaDidShowOrHide(scrollableArea, contentIsVisible); @@ -743,9 +802,8 @@ static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCa closest = candidate; } -void FocusController::findFocusCandidateInContainer(Node* container, const LayoutRect& startingRect, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closest) +void FocusController::findFocusCandidateInContainer(Node& container, const LayoutRect& startingRect, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closest) { - ASSERT(container); Node* focusedNode = (focusedFrame() && focusedFrame()->document()) ? focusedFrame()->document()->focusedElement() : 0; Element* element = ElementTraversal::firstWithin(container); @@ -756,8 +814,8 @@ void FocusController::findFocusCandidateInContainer(Node* container, const Layou unsigned candidateCount = 0; for (; element; element = (element->isFrameOwnerElement() || canScrollInDirection(element, direction)) - ? ElementTraversal::nextSkippingChildren(element, container) - : ElementTraversal::next(element, container)) { + ? ElementTraversal::nextSkippingChildren(*element, &container) + : ElementTraversal::next(*element, &container)) { if (element == focusedNode) continue; @@ -772,7 +830,7 @@ void FocusController::findFocusCandidateInContainer(Node* container, const Layou continue; candidateCount++; - candidate.enclosingScrollableBox = container; + candidate.enclosingScrollableBox = &container; updateFocusCandidateIfNeeded(direction, current, candidate, closest); } @@ -796,7 +854,7 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons // Find the closest node within current container in the direction of the navigation. FocusCandidate focusCandidate; - findFocusCandidateInContainer(container, newStartingRect, direction, event, focusCandidate); + findFocusCandidateInContainer(*container, newStartingRect, direction, event, focusCandidate); if (focusCandidate.isNull()) { // Nothing to focus, scroll if possible. @@ -847,7 +905,7 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons } // We found a new focus node, navigate to it. - Element* element = toElement(focusCandidate.focusableNode); + Element* element = downcast<Element>(focusCandidate.focusableNode); ASSERT(element); element->focus(false, direction); @@ -863,8 +921,8 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa Element* focusedElement = focusedDocument->focusedElement(); Node* container = focusedDocument; - if (container->isDocumentNode()) - toDocument(container)->updateLayoutIgnorePendingStylesheets(); + if (is<Document>(*container)) + downcast<Document>(*container).updateLayoutIgnorePendingStylesheets(); // Figure out the starting rect. LayoutRect startingRect; @@ -872,10 +930,10 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa if (!hasOffscreenRect(focusedElement)) { container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, focusedElement); startingRect = nodeRectInAbsoluteCoordinates(focusedElement, true /* ignore border */); - } else if (isHTMLAreaElement(focusedElement)) { - HTMLAreaElement* area = toHTMLAreaElement(focusedElement); - container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, area->imageElement()); - startingRect = virtualRectForAreaElementAndDirection(area, direction); + } else if (is<HTMLAreaElement>(*focusedElement)) { + HTMLAreaElement& area = downcast<HTMLAreaElement>(*focusedElement); + container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, area.imageElement()); + startingRect = virtualRectForAreaElementAndDirection(&area, direction); } } @@ -887,11 +945,35 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa consumed = advanceFocusDirectionallyInContainer(container, startingRect, direction, event); startingRect = nodeRectInAbsoluteCoordinates(container, true /* ignore border */); container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, container); - if (container && container->isDocumentNode()) - toDocument(container)->updateLayoutIgnorePendingStylesheets(); + if (is<Document>(container)) + downcast<Document>(*container).updateLayoutIgnorePendingStylesheets(); } while (!consumed && container); return consumed; } +void FocusController::setFocusedElementNeedsRepaint() +{ + m_focusRepaintTimer.startOneShot(0.033); +} + +void FocusController::focusRepaintTimerFired() +{ + Document* focusedDocument = focusedOrMainFrame().document(); + if (!focusedDocument) + return; + + Element* focusedElement = focusedDocument->focusedElement(); + if (!focusedElement) + return; + + if (focusedElement->renderer()) + focusedElement->renderer()->repaint(); +} + +double FocusController::timeSinceFocusWasSet() const +{ + return monotonicallyIncreasingTime() - m_focusSetTime; +} + } // namespace WebCore |
