summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/page/FocusController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/page/FocusController.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/core/page/FocusController.cpp394
1 files changed, 206 insertions, 188 deletions
diff --git a/chromium/third_party/WebKit/Source/core/page/FocusController.cpp b/chromium/third_party/WebKit/Source/core/page/FocusController.cpp
index 686e013aa82..a637e983a91 100644
--- a/chromium/third_party/WebKit/Source/core/page/FocusController.cpp
+++ b/chromium/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -27,8 +27,7 @@
#include "config.h"
#include "core/page/FocusController.h"
-#include <limits>
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/accessibility/AXObjectCache.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
@@ -41,14 +40,14 @@
#include "core/editing/FrameSelection.h"
#include "core/editing/htmlediting.h" // For firstPositionInOrBeforeNode
#include "core/events/Event.h"
-#include "core/events/ThreadLocalEventNames.h"
-#include "core/frame/DOMWindow.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalDOMWindow.h"
#include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLAreaElement.h"
#include "core/html/HTMLImageElement.h"
-#include "core/html/HTMLTextAreaElement.h"
-#include "core/html/shadow/HTMLShadowElement.h"
+#include "core/html/HTMLPlugInElement.h"
+#include "core/html/HTMLShadowElement.h"
+#include "core/html/HTMLTextFormControlElement.h"
#include "core/page/Chrome.h"
#include "core/page/ChromeClient.h"
#include "core/page/EventHandler.h"
@@ -57,11 +56,18 @@
#include "core/frame/Settings.h"
#include "core/page/SpatialNavigation.h"
#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderLayer.h"
+#include <limits>
namespace WebCore {
using namespace HTMLNames;
+static inline bool isShadowInsertionPointFocusScopeOwner(Node& node)
+{
+ return isActiveShadowInsertionPoint(node) && toHTMLShadowElement(node).olderShadowRoot();
+}
+
// FIXME: Some of Node* return values and Node* arguments should be Element*.
FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
@@ -72,7 +78,7 @@ FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
Node* FocusNavigationScope::rootNode() const
{
- return m_rootTreeScope->rootNode();
+ return &m_rootTreeScope->rootNode();
}
Element* FocusNavigationScope::owner() const
@@ -82,8 +88,9 @@ Element* FocusNavigationScope::owner() const
ShadowRoot* shadowRoot = toShadowRoot(root);
return shadowRoot->isYoungest() ? shadowRoot->host() : shadowRoot->shadowInsertionPointOfYoungerShadowRoot();
}
+ // FIXME: Figure out the right thing for OOPI here.
if (Frame* frame = root->document().frame())
- return frame->ownerElement();
+ return frame->deprecatedLocalOwner();
return 0;
}
@@ -103,7 +110,7 @@ FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(No
ASSERT(node);
if (isShadowHost(node))
return FocusNavigationScope::ownedByShadowHost(node);
- ASSERT(isActiveShadowInsertionPoint(*node));
+ ASSERT(isShadowInsertionPointFocusScopeOwner(*node));
return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement(node));
}
@@ -115,13 +122,13 @@ FocusNavigationScope FocusNavigationScope::ownedByShadowHost(Node* node)
FocusNavigationScope FocusNavigationScope::ownedByIFrame(HTMLFrameOwnerElement* frame)
{
- ASSERT(frame && frame->contentFrame());
- return FocusNavigationScope(frame->contentFrame()->document());
+ ASSERT(frame && frame->contentFrame() && frame->contentFrame()->isLocalFrame());
+ return FocusNavigationScope(toLocalFrame(frame->contentFrame())->document());
}
FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShadowElement* shadowInsertionPoint)
{
- ASSERT(shadowInsertionPoint->isActive());
+ ASSERT(isShadowInsertionPointFocusScopeOwner(*shadowInsertionPoint));
return FocusNavigationScope(shadowInsertionPoint->olderShadowRoot());
}
@@ -138,7 +145,8 @@ static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool
}
if (!focused && document->focusedElement()) {
- RefPtr<Element> focusedElement(document->focusedElement());
+ RefPtrWillBeRawPtr<Element> focusedElement(document->focusedElement());
+ focusedElement->setFocus(false);
focusedElement->dispatchBlurEvent(0);
if (focusedElement == document->focusedElement()) {
focusedElement->dispatchFocusOutEvent(EventTypeNames::focusout, 0);
@@ -147,11 +155,12 @@ static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool
}
}
- if (DOMWindow* window = document->domWindow())
+ if (LocalDOMWindow* window = document->domWindow())
window->dispatchEvent(Event::create(focused ? EventTypeNames::focus : EventTypeNames::blur));
if (focused && document->focusedElement()) {
- RefPtr<Element> focusedElement(document->focusedElement());
- focusedElement->dispatchFocusEvent(0, FocusDirectionPage);
+ RefPtrWillBeRawPtr<Element> focusedElement(document->focusedElement());
+ focusedElement->setFocus(true);
+ focusedElement->dispatchFocusEvent(0, FocusTypePage);
if (focusedElement == document->focusedElement()) {
document->focusedElement()->dispatchFocusInEvent(EventTypeNames::focusin, 0);
if (focusedElement == document->focusedElement())
@@ -165,7 +174,7 @@ static inline bool hasCustomFocusLogic(Element* element)
return element->isHTMLElement() && toHTMLElement(element)->hasCustomFocusLogic();
}
-#if !ASSERT_DISABLED
+#if ASSERT_ENABLED
static inline bool isNonFocusableShadowHost(Node* node)
{
ASSERT(node);
@@ -197,7 +206,7 @@ static inline bool isKeyboardFocusableShadowHost(Node* node)
static inline bool isNonFocusableFocusScopeOwner(Node* node)
{
ASSERT(node);
- return isNonKeyboardFocusableShadowHost(node) || isActiveShadowInsertionPoint(*node);
+ return isNonKeyboardFocusableShadowHost(node) || isShadowInsertionPointFocusScopeOwner(*node);
}
static inline int adjustedTabIndex(Node* node)
@@ -217,7 +226,6 @@ FocusController::FocusController(Page* page)
, m_isActive(false)
, m_isFocused(false)
, m_isChangingFocusedFrame(false)
- , m_containingWindowIsVisible(false)
{
}
@@ -234,10 +242,10 @@ void FocusController::setFocusedFrame(PassRefPtr<Frame> frame)
m_isChangingFocusedFrame = true;
- RefPtr<Frame> oldFrame = m_focusedFrame;
- RefPtr<Frame> newFrame = frame;
+ RefPtr<LocalFrame> oldFrame = (m_focusedFrame && m_focusedFrame->isLocalFrame()) ? toLocalFrame(m_focusedFrame.get()) : 0;
+ RefPtr<LocalFrame> newFrame = (frame && frame->isLocalFrame()) ? toLocalFrame(frame.get()) : 0;
- m_focusedFrame = newFrame;
+ m_focusedFrame = frame.get();
// Now that the frame is updated, fire events and update the selection focused states of both frames.
if (oldFrame && oldFrame->view()) {
@@ -251,6 +259,45 @@ void FocusController::setFocusedFrame(PassRefPtr<Frame> frame)
}
m_isChangingFocusedFrame = false;
+
+ m_page->chrome().client().focusedFrameChanged(newFrame.get());
+}
+
+void FocusController::focusDocumentView(PassRefPtr<Frame> frame)
+{
+ ASSERT(!frame || frame->page() == m_page);
+ if (m_focusedFrame == frame)
+ return;
+
+ RefPtr<LocalFrame> focusedFrame = (m_focusedFrame && m_focusedFrame->isLocalFrame()) ? toLocalFrame(m_focusedFrame.get()) : 0;
+ if (focusedFrame && focusedFrame->view()) {
+ RefPtrWillBeRawPtr<Document> document = focusedFrame->document();
+ Element* focusedElement = document ? document->focusedElement() : 0;
+ if (focusedElement) {
+ focusedElement->dispatchBlurEvent(0);
+ if (focusedElement == document->focusedElement()) {
+ focusedElement->dispatchFocusOutEvent(EventTypeNames::focusout, 0);
+ if (focusedElement == document->focusedElement())
+ focusedElement->dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, 0);
+ }
+ }
+ }
+
+ RefPtr<LocalFrame> newFocusedFrame = (frame && frame->isLocalFrame()) ? toLocalFrame(frame.get()) : 0;
+ if (newFocusedFrame && newFocusedFrame->view()) {
+ RefPtrWillBeRawPtr<Document> document = newFocusedFrame->document();
+ Element* focusedElement = document ? document->focusedElement() : 0;
+ if (focusedElement) {
+ focusedElement->dispatchFocusEvent(0, FocusTypePage);
+ if (focusedElement == document->focusedElement()) {
+ document->focusedElement()->dispatchFocusInEvent(EventTypeNames::focusin, 0);
+ if (focusedElement == document->focusedElement())
+ document->focusedElement()->dispatchFocusInEvent(EventTypeNames::DOMFocusIn, 0);
+ }
+ }
+ }
+
+ setFocusedFrame(frame);
}
Frame* FocusController::focusedOrMainFrame() const
@@ -267,28 +314,30 @@ void FocusController::setFocused(bool focused)
m_isFocused = focused;
- if (!m_isFocused)
- focusedOrMainFrame()->eventHandler().stopAutoscroll();
+ if (!m_isFocused && focusedOrMainFrame()->isLocalFrame())
+ toLocalFrame(focusedOrMainFrame())->eventHandler().stopAutoscroll();
if (!m_focusedFrame)
setFocusedFrame(m_page->mainFrame());
- if (m_focusedFrame->view()) {
- m_focusedFrame->selection().setFocused(focused);
- dispatchEventsOnWindowAndFocusedNode(m_focusedFrame->document(), focused);
+ // setFocusedFrame above might reject to update m_focusedFrame, or
+ // m_focusedFrame might be changed by blur/focus event handlers.
+ if (m_focusedFrame && m_focusedFrame->isLocalFrame() && toLocalFrame(m_focusedFrame.get())->view()) {
+ toLocalFrame(m_focusedFrame.get())->selection().setFocused(focused);
+ dispatchEventsOnWindowAndFocusedNode(toLocalFrame(m_focusedFrame.get())->document(), focused);
}
}
-Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(FocusDirection direction, Node* node)
+Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(FocusType type, Node* node)
{
// 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 (node && node->isFrameOwnerElement()) {
HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(node);
- if (!owner->contentFrame())
+ if (!owner->contentFrame() || !owner->contentFrame()->isLocalFrame())
break;
- Node* foundNode = findFocusableNode(direction, FocusNavigationScope::ownedByIFrame(owner), 0);
+ Node* foundNode = findFocusableNode(type, FocusNavigationScope::ownedByIFrame(owner), 0);
if (!foundNode)
break;
ASSERT(node != foundNode);
@@ -297,30 +346,33 @@ Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(FocusDire
return node;
}
-bool FocusController::setInitialFocus(FocusDirection direction)
+bool FocusController::setInitialFocus(FocusType type)
{
- bool didAdvanceFocus = advanceFocus(direction, true);
+ bool didAdvanceFocus = advanceFocus(type, true);
// If focus is being set initially, accessibility needs to be informed that system focus has moved
// into the web area again, even if focus did not change within WebCore. PostNotification is called instead
// of handleFocusedUIElementChanged, because this will send the notification even if the element is the same.
- if (AXObjectCache* cache = focusedOrMainFrame()->document()->existingAXObjectCache())
- cache->postNotification(focusedOrMainFrame()->document(), AXObjectCache::AXFocusedUIElementChanged, true);
+ if (focusedOrMainFrame()->isLocalFrame()) {
+ Document* document = toLocalFrame(focusedOrMainFrame())->document();
+ if (AXObjectCache* cache = document->existingAXObjectCache())
+ cache->postNotification(document, AXObjectCache::AXFocusedUIElementChanged, true);
+ }
return didAdvanceFocus;
}
-bool FocusController::advanceFocus(FocusDirection direction, bool initialFocus)
+bool FocusController::advanceFocus(FocusType type, bool initialFocus)
{
- switch (direction) {
- case FocusDirectionForward:
- case FocusDirectionBackward:
- return advanceFocusInDocumentOrder(direction, initialFocus);
- case FocusDirectionLeft:
- case FocusDirectionRight:
- case FocusDirectionUp:
- case FocusDirectionDown:
- return advanceFocusDirectionally(direction);
+ switch (type) {
+ case FocusTypeForward:
+ case FocusTypeBackward:
+ return advanceFocusInDocumentOrder(type, initialFocus);
+ case FocusTypeLeft:
+ case FocusTypeRight:
+ case FocusTypeUp:
+ case FocusTypeDown:
+ return advanceFocusDirectionally(type);
default:
ASSERT_NOT_REACHED();
}
@@ -328,9 +380,13 @@ bool FocusController::advanceFocus(FocusDirection direction, bool initialFocus)
return false;
}
-bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, bool initialFocus)
+bool FocusController::advanceFocusInDocumentOrder(FocusType type, bool initialFocus)
{
- Frame* frame = focusedOrMainFrame();
+ // FIXME: Focus advancement won't work with externally rendered frames until after
+ // inter-frame focus control is moved out of Blink.
+ if (!focusedOrMainFrame()->isLocalFrame())
+ return false;
+ LocalFrame* frame = toLocalFrame(focusedOrMainFrame());
ASSERT(frame);
Document* document = frame->document();
@@ -343,20 +399,22 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, bool
document->updateLayoutIgnorePendingStylesheets();
- RefPtr<Node> node = findFocusableNodeAcrossFocusScope(direction, FocusNavigationScope::focusNavigationScopeOf(currentNode ? currentNode : document), currentNode);
+ RefPtrWillBeRawPtr<Node> node = findFocusableNodeAcrossFocusScope(type, FocusNavigationScope::focusNavigationScopeOf(currentNode ? currentNode : document), currentNode);
if (!node) {
// 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);
- m_page->chrome().takeFocus(direction);
+ if (!initialFocus && m_page->chrome().canTakeFocus(type)) {
+ document->setFocusedElement(nullptr);
+ setFocusedFrame(nullptr);
+ m_page->chrome().takeFocus(type);
return true;
}
// Chrome doesn't want focus, so we should wrap focus.
- node = findFocusableNodeRecursively(direction, FocusNavigationScope::focusNavigationScopeOf(m_page->mainFrame()->document()), 0);
- node = findFocusableNodeDecendingDownIntoFrameDocument(direction, node.get());
+ if (!m_page->mainFrame()->isLocalFrame())
+ return false;
+ node = findFocusableNodeRecursively(type, FocusNavigationScope::focusNavigationScopeOf(m_page->deprecatedLocalMainFrame()->document()), 0);
+ node = findFocusableNodeDecendingDownIntoFrameDocument(type, node.get());
if (!node)
return false;
@@ -373,14 +431,14 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, bool
return false;
Element* element = toElement(node);
- if (element->isFrameOwnerElement() && (!element->isPluginElement() || !element->isKeyboardFocusable())) {
+ if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !element->isKeyboardFocusable())) {
// 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);
if (!owner->contentFrame())
return false;
- document->setFocusedElement(0);
+ document->setFocusedElement(nullptr);
setFocusedFrame(owner->contentFrame());
return true;
}
@@ -392,7 +450,7 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, bool
if (&newDocument != document) {
// Focus is going away from this document, so clear the focused node.
- document->setFocusedElement(0);
+ document->setFocusedElement(nullptr);
}
setFocusedFrame(newDocument.frame());
@@ -403,19 +461,19 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, bool
frame->selection().setSelection(newSelection);
}
- element->focus(false, direction);
+ element->focus(false, type);
return true;
}
-Node* FocusController::findFocusableNodeAcrossFocusScope(FocusDirection direction, FocusNavigationScope scope, Node* currentNode)
+Node* FocusController::findFocusableNodeAcrossFocusScope(FocusType type, FocusNavigationScope scope, Node* currentNode)
{
ASSERT(!currentNode || !isNonFocusableShadowHost(currentNode));
Node* found;
- if (currentNode && direction == FocusDirectionForward && isKeyboardFocusableShadowHost(currentNode)) {
- Node* foundInInnerFocusScope = findFocusableNodeRecursively(direction, FocusNavigationScope::ownedByShadowHost(currentNode), 0);
- found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNodeRecursively(direction, scope, currentNode);
+ if (currentNode && type == FocusTypeForward && isKeyboardFocusableShadowHost(currentNode)) {
+ Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusNavigationScope::ownedByShadowHost(currentNode), 0);
+ found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNodeRecursively(type, scope, currentNode);
} else {
- found = findFocusableNodeRecursively(direction, scope, currentNode);
+ found = findFocusableNodeRecursively(type, scope, currentNode);
}
// If there's no focusable node to advance to, move up the focus scopes until we find one.
@@ -424,51 +482,49 @@ Node* FocusController::findFocusableNodeAcrossFocusScope(FocusDirection directio
if (!owner)
break;
scope = FocusNavigationScope::focusNavigationScopeOf(owner);
- if (direction == FocusDirectionBackward && isKeyboardFocusableShadowHost(owner)) {
+ if (type == FocusTypeBackward && isKeyboardFocusableShadowHost(owner)) {
found = owner;
break;
}
- found = findFocusableNodeRecursively(direction, scope, owner);
+ found = findFocusableNodeRecursively(type, scope, owner);
}
- found = findFocusableNodeDecendingDownIntoFrameDocument(direction, found);
+ found = findFocusableNodeDecendingDownIntoFrameDocument(type, found);
return found;
}
-Node* FocusController::findFocusableNodeRecursively(FocusDirection direction, FocusNavigationScope scope, Node* start)
+Node* FocusController::findFocusableNodeRecursively(FocusType type, FocusNavigationScope scope, Node* start)
{
// Starting node is exclusive.
- Node* found = findFocusableNode(direction, scope, start);
+ Node* found = findFocusableNode(type, scope, start);
if (!found)
return 0;
- if (direction == FocusDirectionForward) {
+ if (type == FocusTypeForward) {
if (!isNonFocusableFocusScopeOwner(found))
return found;
- Node* foundInInnerFocusScope = findFocusableNodeRecursively(direction, FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(found), 0);
- return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNodeRecursively(direction, scope, found);
+ Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(found), 0);
+ return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNodeRecursively(type, scope, found);
}
- ASSERT(direction == FocusDirectionBackward);
+ ASSERT(type == FocusTypeBackward);
if (isKeyboardFocusableShadowHost(found)) {
- Node* foundInInnerFocusScope = findFocusableNodeRecursively(direction, FocusNavigationScope::ownedByShadowHost(found), 0);
+ Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusNavigationScope::ownedByShadowHost(found), 0);
return foundInInnerFocusScope ? foundInInnerFocusScope : found;
}
if (isNonFocusableFocusScopeOwner(found)) {
- Node* foundInInnerFocusScope = findFocusableNodeRecursively(direction, FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(found), 0);
- return foundInInnerFocusScope ? foundInInnerFocusScope :findFocusableNodeRecursively(direction, scope, found);
+ Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(found), 0);
+ return foundInInnerFocusScope ? foundInInnerFocusScope :findFocusableNodeRecursively(type, scope, found);
}
return found;
}
-Node* FocusController::findFocusableNode(FocusDirection direction, FocusNavigationScope scope, Node* node)
+Node* FocusController::findFocusableNode(FocusType type, FocusNavigationScope scope, Node* node)
{
- return (direction == FocusDirectionForward)
- ? nextFocusableNode(scope, node)
- : previousFocusableNode(scope, node);
+ return type == FocusTypeForward ? nextFocusableNode(scope, node) : previousFocusableNode(scope, node);
}
-Node* FocusController::findNodeWithExactTabIndex(Node* start, int tabIndex, FocusDirection direction)
+Node* FocusController::findNodeWithExactTabIndex(Node* start, int tabIndex, FocusType type)
{
// Search is inclusive of start
- for (Node* node = start; node; node = direction == FocusDirectionForward ? NodeTraversal::next(*node) : NodeTraversal::previous(*node)) {
+ for (Node* node = start; node; node = type == FocusTypeForward ? NodeTraversal::next(*node) : NodeTraversal::previous(*node)) {
if (shouldVisit(node) && adjustedTabIndex(node) == tabIndex)
return node;
}
@@ -518,7 +574,7 @@ Node* FocusController::nextFocusableNode(FocusNavigationScope scope, Node* start
}
// First try to find a node with the same tabindex as start that comes after start in the scope.
- if (Node* winner = findNodeWithExactTabIndex(NodeTraversal::next(*start), tabIndex, FocusDirectionForward))
+ if (Node* winner = findNodeWithExactTabIndex(NodeTraversal::next(*start), tabIndex, FocusTypeForward))
return winner;
if (!tabIndex)
@@ -534,7 +590,7 @@ Node* FocusController::nextFocusableNode(FocusNavigationScope scope, Node* start
// There are no nodes with a tabindex greater than start's tabindex,
// so find the first node with a tabindex of 0.
- return findNodeWithExactTabIndex(scope.rootNode(), 0, FocusDirectionForward);
+ return findNodeWithExactTabIndex(scope.rootNode(), 0, FocusTypeForward);
}
Node* FocusController::previousFocusableNode(FocusNavigationScope scope, Node* start)
@@ -564,7 +620,7 @@ Node* FocusController::previousFocusableNode(FocusNavigationScope scope, Node* s
}
}
- if (Node* winner = findNodeWithExactTabIndex(startingNode, startingTabIndex, FocusDirectionBackward))
+ if (Node* winner = findNodeWithExactTabIndex(startingNode, startingTabIndex, FocusTypeBackward))
return winner;
// There are no nodes before start with the same tabindex as start, so look for a node that:
@@ -581,7 +637,7 @@ static bool relinquishesEditingFocus(Node *node)
return node->document().frame() && node->rootEditableElement();
}
-static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFrame, Node* newFocusedNode)
+static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newFocusedFrame, Node* newFocusedNode)
{
if (!oldFocusedFrame || !newFocusedFrame)
return;
@@ -603,25 +659,20 @@ static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFram
if (Node* mousePressNode = newFocusedFrame->eventHandler().mousePressNode()) {
if (mousePressNode->renderer() && !mousePressNode->canStartSelection()) {
- // Don't clear the selection for contentEditable elements, but do clear it for input and textarea. See bug 38696.
- Node* root = selection.rootEditableElement();
- if (!root)
+ // Don't clear the selection for contentEditable elements, but do
+ // clear it for input and textarea. See bug 38696.
+ if (!enclosingTextFormControl(selection.start()))
return;
-
- if (Node* shadowAncestorNode = root->deprecatedShadowAncestorNode()) {
- if (!shadowAncestorNode->hasTagName(inputTag) && !isHTMLTextAreaElement(shadowAncestorNode))
- return;
- }
}
}
selection.clear();
}
-bool FocusController::setFocusedElement(Element* element, PassRefPtr<Frame> newFocusedFrame, FocusDirection direction)
+bool FocusController::setFocusedElement(Element* element, PassRefPtr<Frame> newFocusedFrame, FocusType type)
{
- RefPtr<Frame> oldFocusedFrame = focusedFrame();
- RefPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0;
+ RefPtr<LocalFrame> oldFocusedFrame = toLocalFrame(focusedFrame());
+ RefPtrWillBeRawPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0;
Element* oldFocusedElement = oldDocument ? oldDocument->focusedElement() : 0;
if (element && oldFocusedElement == element)
@@ -633,30 +684,30 @@ bool FocusController::setFocusedElement(Element* element, PassRefPtr<Frame> newF
m_page->chrome().client().willSetInputMethodState();
- RefPtr<Document> newDocument;
+ RefPtrWillBeRawPtr<Document> newDocument = nullptr;
if (element)
newDocument = &element->document();
- else if (newFocusedFrame)
- newDocument = newFocusedFrame->document();
+ else if (newFocusedFrame && newFocusedFrame->isLocalFrame())
+ newDocument = toLocalFrame(newFocusedFrame.get())->document();
if (newDocument && oldDocument == newDocument && newDocument->focusedElement() == element)
return true;
- clearSelectionIfNeeded(oldFocusedFrame.get(), newFocusedFrame.get(), element);
+ clearSelectionIfNeeded(oldFocusedFrame.get(), toLocalFrame(newFocusedFrame.get()), element);
if (oldDocument && oldDocument != newDocument)
- oldDocument->setFocusedElement(0);
+ oldDocument->setFocusedElement(nullptr);
if (newFocusedFrame && !newFocusedFrame->page()) {
- setFocusedFrame(0);
+ setFocusedFrame(nullptr);
return false;
}
setFocusedFrame(newFocusedFrame);
// Setting the focused node can result in losing our last reft to node when JS event handlers fire.
- RefPtr<Element> protect = element;
+ RefPtrWillBeRawPtr<Element> protect ALLOW_UNUSED = element;
if (newDocument) {
- bool successfullyFocused = newDocument->setFocusedElement(element, direction);
+ bool successfullyFocused = newDocument->setFocusedElement(element, type);
if (!successfullyFocused)
return false;
}
@@ -671,54 +722,15 @@ void FocusController::setActive(bool active)
m_isActive = active;
- if (FrameView* view = m_page->mainFrame()->view()) {
- view->updateLayoutAndStyleIfNeededRecursive();
- view->updateControlTints();
+ if (m_page->mainFrame()->isLocalFrame()) {
+ if (FrameView* view = m_page->deprecatedLocalMainFrame()->view())
+ view->updateControlTints();
}
- focusedOrMainFrame()->selection().pageActivationChanged();
-}
-
-static void contentAreaDidShowOrHide(ScrollableArea* scrollableArea, bool didShow)
-{
- if (didShow)
- scrollableArea->contentAreaDidShow();
- else
- scrollableArea->contentAreaDidHide();
-}
-
-void FocusController::setContainingWindowIsVisible(bool containingWindowIsVisible)
-{
- if (m_containingWindowIsVisible == containingWindowIsVisible)
- return;
-
- m_containingWindowIsVisible = containingWindowIsVisible;
-
- FrameView* view = m_page->mainFrame()->view();
- if (!view)
- return;
-
- contentAreaDidShowOrHide(view, containingWindowIsVisible);
-
- for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
- FrameView* frameView = frame->view();
- if (!frameView)
- continue;
-
- const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
- if (!scrollableAreas)
- continue;
-
- for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
- ScrollableArea* scrollableArea = *it;
- ASSERT(scrollableArea->scrollbarsCanBeActive());
-
- contentAreaDidShowOrHide(scrollableArea, containingWindowIsVisible);
- }
- }
+ toLocalFrame(focusedOrMainFrame())->selection().pageActivationChanged();
}
-static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCandidate& current, FocusCandidate& candidate, FocusCandidate& closest)
+static void updateFocusCandidateIfNeeded(FocusType type, const FocusCandidate& current, FocusCandidate& candidate, FocusCandidate& closest)
{
ASSERT(candidate.visibleNode->isElementNode());
ASSERT(candidate.visibleNode->renderer());
@@ -728,10 +740,10 @@ static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCa
return;
// Ignore off screen child nodes of containers that do not scroll (overflow:hidden)
- if (candidate.isOffscreen && !canBeScrolledIntoView(direction, candidate))
+ if (candidate.isOffscreen && !canBeScrolledIntoView(type, candidate))
return;
- distanceDataForNode(direction, current, candidate);
+ distanceDataForNode(type, current, candidate);
if (candidate.distance == maxDistance())
return;
@@ -744,11 +756,14 @@ static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCa
}
LayoutRect intersectionRect = intersection(candidate.rect, closest.rect);
- if (!intersectionRect.isEmpty() && !areElementsOnSameLine(closest, candidate)) {
+ if (!intersectionRect.isEmpty() && !areElementsOnSameLine(closest, candidate)
+ && intersectionRect == candidate.rect) {
// If 2 nodes are intersecting, do hit test to find which node in on top.
LayoutUnit x = intersectionRect.x() + intersectionRect.width() / 2;
LayoutUnit y = intersectionRect.y() + intersectionRect.height() / 2;
- HitTestResult result = candidate.visibleNode->document().page()->mainFrame()->eventHandler().hitTestResultAtPoint(IntPoint(x, y), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
+ if (!candidate.visibleNode->document().page()->mainFrame()->isLocalFrame())
+ return;
+ HitTestResult result = candidate.visibleNode->document().page()->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(IntPoint(x, y), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
if (candidate.visibleNode->contains(result.innerNode())) {
closest = candidate;
return;
@@ -767,9 +782,9 @@ static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCa
closest = candidate;
}
-void FocusController::findFocusCandidateInContainer(Node& container, const LayoutRect& startingRect, FocusDirection direction, FocusCandidate& closest)
+void FocusController::findFocusCandidateInContainer(Node& container, const LayoutRect& startingRect, FocusType type, FocusCandidate& closest)
{
- Element* focusedElement = (focusedFrame() && focusedFrame()->document()) ? focusedFrame()->document()->focusedElement() : 0;
+ Element* focusedElement = (focusedFrame() && toLocalFrame(focusedFrame())->document()) ? toLocalFrame(focusedFrame())->document()->focusedElement() : 0;
Element* element = ElementTraversal::firstWithin(container);
FocusCandidate current;
@@ -777,25 +792,25 @@ void FocusController::findFocusCandidateInContainer(Node& container, const Layou
current.focusableNode = focusedElement;
current.visibleNode = focusedElement;
- for (; element; element = (element->isFrameOwnerElement() || canScrollInDirection(element, direction))
+ for (; element; element = (element->isFrameOwnerElement() || canScrollInDirection(element, type))
? ElementTraversal::nextSkippingChildren(*element, &container)
: ElementTraversal::next(*element, &container)) {
if (element == focusedElement)
continue;
- if (!element->isKeyboardFocusable() && !element->isFrameOwnerElement() && !canScrollInDirection(element, direction))
+ if (!element->isKeyboardFocusable() && !element->isFrameOwnerElement() && !canScrollInDirection(element, type))
continue;
- FocusCandidate candidate = FocusCandidate(element, direction);
+ FocusCandidate candidate = FocusCandidate(element, type);
if (candidate.isNull())
continue;
candidate.enclosingScrollableBox = &container;
- updateFocusCandidateIfNeeded(direction, current, candidate, closest);
+ updateFocusCandidateIfNeeded(type, current, candidate, closest);
}
}
-bool FocusController::advanceFocusDirectionallyInContainer(Node* container, const LayoutRect& startingRect, FocusDirection direction)
+bool FocusController::advanceFocusDirectionallyInContainer(Node* container, const LayoutRect& startingRect, FocusType type)
{
if (!container)
return false;
@@ -803,57 +818,57 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
LayoutRect newStartingRect = startingRect;
if (startingRect.isEmpty())
- newStartingRect = virtualRectForDirection(direction, nodeRectInAbsoluteCoordinates(container));
+ newStartingRect = virtualRectForDirection(type, nodeRectInAbsoluteCoordinates(container));
// Find the closest node within current container in the direction of the navigation.
FocusCandidate focusCandidate;
- findFocusCandidateInContainer(*container, newStartingRect, direction, focusCandidate);
+ findFocusCandidateInContainer(*container, newStartingRect, type, focusCandidate);
if (focusCandidate.isNull()) {
// 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);
+ return scrollInDirection(container, type);
}
- 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());
-
+ 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 || frameElement->contentFrame());
+ if (frameElement && frameElement->contentFrame()->isLocalFrame()) {
if (focusCandidate.isOffscreenAfterScrolling) {
- scrollInDirection(&focusCandidate.visibleNode->document(), direction);
+ scrollInDirection(&focusCandidate.visibleNode->document(), type);
return true;
}
// Navigate into a new frame.
LayoutRect rect;
- Element* focusedElement = focusedOrMainFrame()->document()->focusedElement();
+ Element* focusedElement = toLocalFrame(focusedOrMainFrame())->document()->focusedElement();
if (focusedElement && !hasOffscreenRect(focusedElement))
rect = nodeRectInAbsoluteCoordinates(focusedElement, true /* ignore border */);
- frameElement->contentFrame()->document()->updateLayoutIgnorePendingStylesheets();
- if (!advanceFocusDirectionallyInContainer(frameElement->contentFrame()->document(), rect, direction)) {
+ toLocalFrame(frameElement->contentFrame())->document()->updateLayoutIgnorePendingStylesheets();
+ if (!advanceFocusDirectionallyInContainer(toLocalFrame(frameElement->contentFrame())->document(), rect, type)) {
// The new frame had nothing interesting, need to find another candidate.
- return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.visibleNode, true), direction);
+ return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.visibleNode, true), type);
}
return true;
}
- if (canScrollInDirection(focusCandidate.visibleNode, direction)) {
+ if (canScrollInDirection(focusCandidate.visibleNode, type)) {
if (focusCandidate.isOffscreenAfterScrolling) {
- scrollInDirection(focusCandidate.visibleNode, direction);
+ scrollInDirection(focusCandidate.visibleNode, type);
return true;
}
// Navigate into a new scrollable container.
LayoutRect startingRect;
- Element* focusedElement = focusedOrMainFrame()->document()->focusedElement();
+ Element* focusedElement = toLocalFrame(focusedOrMainFrame())->document()->focusedElement();
if (focusedElement && !hasOffscreenRect(focusedElement))
startingRect = nodeRectInAbsoluteCoordinates(focusedElement, true);
- return advanceFocusDirectionallyInContainer(focusCandidate.visibleNode, startingRect, direction);
+ return advanceFocusDirectionallyInContainer(focusCandidate.visibleNode, startingRect, type);
}
if (focusCandidate.isOffscreenAfterScrolling) {
Node* container = focusCandidate.enclosingScrollableBox;
- scrollInDirection(container, direction);
+ scrollInDirection(container, type);
return true;
}
@@ -861,13 +876,16 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
Element* element = toElement(focusCandidate.focusableNode);
ASSERT(element);
- element->focus(false, direction);
+ element->focus(false, type);
return true;
}
-bool FocusController::advanceFocusDirectionally(FocusDirection direction)
+bool FocusController::advanceFocusDirectionally(FocusType type)
{
- Frame* curFrame = focusedOrMainFrame();
+ // FIXME: Directional focus changes don't yet work with RemoteFrames.
+ if (!focusedOrMainFrame()->isLocalFrame())
+ return false;
+ LocalFrame* curFrame = toLocalFrame(focusedOrMainFrame());
ASSERT(curFrame);
Document* focusedDocument = curFrame->document();
@@ -884,20 +902,20 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction)
LayoutRect startingRect;
if (focusedElement) {
if (!hasOffscreenRect(focusedElement)) {
- container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, focusedElement);
+ container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(type, 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 (isHTMLAreaElement(*focusedElement)) {
+ HTMLAreaElement& area = toHTMLAreaElement(*focusedElement);
+ container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(type, area.imageElement());
+ startingRect = virtualRectForAreaElementAndDirection(area, type);
}
}
bool consumed = false;
do {
- consumed = advanceFocusDirectionallyInContainer(container, startingRect, direction);
+ consumed = advanceFocusDirectionallyInContainer(container, startingRect, type);
startingRect = nodeRectInAbsoluteCoordinates(container, true /* ignore border */);
- container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, container);
+ container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(type, container);
if (container && container->isDocumentNode())
toDocument(container)->updateLayoutIgnorePendingStylesheets();
} while (!consumed && container);