Index: Source/core/dom/Element.cpp |
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp |
index 943459796b164060b9f801ac09003f4a163cf835..2bcfb67b9a39ed486f56b3938113cfb869bafdef 100644 |
--- a/Source/core/dom/Element.cpp |
+++ b/Source/core/dom/Element.cpp |
@@ -76,6 +76,7 @@ |
#include "core/events/FocusEvent.h" |
#include "core/frame/FrameView.h" |
#include "core/frame/LocalFrame.h" |
+#include "core/frame/Settings.h" |
#include "core/frame/UseCounter.h" |
#include "core/frame/csp/ContentSecurityPolicy.h" |
#include "core/html/ClassList.h" |
@@ -232,6 +233,11 @@ void Element::setTabIndexExplicitly(short tabIndex) |
ensureElementRareData().setTabIndexExplicitly(tabIndex); |
} |
+void Element::setTabIndex(int value) |
+{ |
+ setIntegralAttribute(tabindexAttr, value); |
+} |
+ |
short Element::tabIndex() const |
{ |
return hasRareData() ? elementRareData()->tabIndex() : 0; |
@@ -1926,6 +1932,24 @@ PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionState& except |
return guard.release(); |
} |
+void Element::parseAttribute(const QualifiedName& name, const AtomicString& value) |
+{ |
+ if (name == tabindexAttr) { |
+ int tabindex = 0; |
+ if (value.isEmpty()) { |
+ clearTabIndexExplicitlyIfNeeded(); |
+ if (treeScope().adjustedFocusedElement() == this) { |
+ // We might want to call blur(), but it's dangerous to dispatch |
+ // events here. |
+ document().setNeedsFocusedElementCheck(); |
+ } |
+ } else if (parseHTMLInteger(value, tabindex)) { |
+ // Clamp tabindex to the range of 'short' to match Firefox's behavior. |
+ setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), std::min(tabindex, static_cast<int>(std::numeric_limits<short>::max())))); |
+ } |
+ } |
+} |
+ |
bool Element::parseAttributeName(QualifiedName& out, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState& exceptionState) |
{ |
AtomicString prefix, localName; |
@@ -2120,6 +2144,33 @@ void Element::blur() |
} |
} |
+bool Element::supportsFocus() const |
+{ |
+ // FIXME: supportsFocus() can be called when layout is not up to date. |
+ // Logic that deals with the renderer should be moved to rendererIsFocusable(). |
+ // But supportsFocus must return true when the element is editable, or else |
+ // it won't be focusable. Furthermore, supportsFocus cannot just return true |
+ // always or else tabIndex() will change for all HTML elements. |
+ return hasElementFlag(TabIndexWasSetExplicitly) || (rendererIsEditable() && parentNode() && !parentNode()->rendererIsEditable()) |
+ || supportsSpatialNavigationFocus(); |
+} |
+ |
+bool Element::supportsSpatialNavigationFocus() const |
+{ |
+ // This function checks whether the element satisfies the extended criteria |
+ // for the element to be focusable, introduced by spatial navigation feature, |
+ // i.e. checks if click or keyboard event handler is specified. |
+ // This is the way to make it possible to navigate to (focus) elements |
+ // which web designer meant for being active (made them respond to click events). |
+ |
+ if (!document().settings() || !document().settings()->spatialNavigationEnabled()) |
+ return false; |
+ return hasEventListeners(EventTypeNames::click) |
+ || hasEventListeners(EventTypeNames::keydown) |
+ || hasEventListeners(EventTypeNames::keypress) |
+ || hasEventListeners(EventTypeNames::keyup); |
+} |
+ |
bool Element::isFocusable() const |
{ |
return inDocument() && supportsFocus() && !isInert() && rendererIsFocusable(); |