Bug 778654 - Implement and move tabIndex functions to Element class to avoid duplicate work; r?heycam, peterv
MozReview-Commit-ID: uetkJztNcn
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -286,16 +286,65 @@ Element::UpdateEditableState(bool aNotif
AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
} else {
RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
}
}
}
+int32_t
+Element::TabIndex()
+{
+ const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::tabindex);
+ if (attrVal && attrVal->Type() == nsAttrValue::eInteger) {
+ return attrVal->GetIntegerValue();
+ }
+
+ return TabIndexDefault();
+}
+
+void
+Element::Focus(mozilla::ErrorResult& aError)
+{
+ nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
+ nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+ if (fm && domElement) {
+ aError = fm->SetFocus(domElement, 0);
+ }
+}
+
+void
+Element::SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError)
+{
+ nsAutoString value;
+ value.AppendInt(aTabIndex);
+
+ SetAttr(nsGkAtoms::tabindex, value, aError);
+}
+
+void
+Element::Blur(mozilla::ErrorResult& aError)
+{
+ if (!ShouldBlur(this)) {
+ return;
+ }
+
+ nsIDocument* doc = GetComposedDoc();
+ if (!doc) {
+ return;
+ }
+
+ nsPIDOMWindowOuter* win = doc->GetWindow();
+ nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+ if (win && fm) {
+ aError = fm->ClearFocus(win);
+ }
+}
+
EventStates
Element::StyleStateFromLocks() const
{
EventStates locks = LockedStyleStates();
EventStates state = mState | locks;
if (locks.HasState(NS_EVENT_STATE_VISITED)) {
return state & ~NS_EVENT_STATE_UNVISITED;
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -188,16 +188,41 @@ public:
*/
void UpdateState(bool aNotify);
/**
* Method to update mState with link state information. This does not notify.
*/
void UpdateLinkState(EventStates aState);
+ virtual int32_t TabIndexDefault()
+ {
+ return -1;
+ }
+
+ /**
+ * Get tabIndex of this element. If not found, return TabIndexDefault.
+ */
+ int32_t TabIndex();
+
+ /**
+ * Set tabIndex value to this element.
+ */
+ void SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError);
+
+ /**
+ * Make focus on this element.
+ */
+ virtual void Focus(mozilla::ErrorResult& aError);
+
+ /**
+ * Show blur and clear focus.
+ */
+ virtual void Blur(mozilla::ErrorResult& aError);
+
/**
* The style state of this element. This is the real state of the element
* with any style locks applied for pseudo-class inspecting.
*/
EventStates StyleState() const
{
if (!HasLockedStyleStates()) {
return mState;
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -2618,44 +2618,16 @@ nsGenericHTMLFormElement::IsLabelable()
type == NS_FORM_OUTPUT ||
type == NS_FORM_SELECT ||
type == NS_FORM_TEXTAREA;
}
//----------------------------------------------------------------------
void
-nsGenericHTMLElement::Blur(mozilla::ErrorResult& aError)
-{
- if (!ShouldBlur(this)) {
- return;
- }
-
- nsIDocument* doc = GetComposedDoc();
- if (!doc) {
- return;
- }
-
- nsPIDOMWindowOuter* win = doc->GetWindow();
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- if (win && fm) {
- aError = fm->ClearFocus(win);
- }
-}
-
-void
-nsGenericHTMLElement::Focus(ErrorResult& aError)
-{
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- if (fm) {
- aError = fm->SetFocus(this, 0);
- }
-}
-
-void
nsGenericHTMLElement::Click()
{
if (HandlingClick())
return;
// Strong in case the event kills it
nsCOMPtr<nsIDocument> doc = GetComposedDoc();
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -46,16 +46,18 @@ typedef nsMappedAttributeElement nsGener
/**
* A common superclass for HTML elements
*/
class nsGenericHTMLElement : public nsGenericHTMLElementBase,
public nsIDOMHTMLElement
{
public:
+ using Element::SetTabIndex;
+ using Element::Focus;
explicit nsGenericHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElementBase(aNodeInfo)
{
NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
"Unexpected namespace");
AddStatesSilently(NS_EVENT_STATE_LTR);
SetFlags(NODE_HAS_DIRECTION_LTR);
}
@@ -98,30 +100,16 @@ public:
{
return GetBoolAttr(nsGkAtoms::hidden);
}
void SetHidden(bool aHidden, mozilla::ErrorResult& aError)
{
SetHTMLBoolAttr(nsGkAtoms::hidden, aHidden, aError);
}
virtual void Click();
- virtual int32_t TabIndexDefault()
- {
- return -1;
- }
- int32_t TabIndex()
- {
- return GetIntAttr(nsGkAtoms::tabindex, TabIndexDefault());
- }
- void SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError)
- {
- SetHTMLIntAttr(nsGkAtoms::tabindex, aTabIndex, aError);
- }
- virtual void Focus(mozilla::ErrorResult& aError);
- virtual void Blur(mozilla::ErrorResult& aError);
void GetAccessKey(nsString& aAccessKey)
{
GetHTMLAttr(nsGkAtoms::accesskey, aAccessKey);
}
void SetAccessKey(const nsAString& aAccessKey, mozilla::ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::accesskey, aAccessKey, aError);
}
--- a/dom/svg/SVGAElement.cpp
+++ b/dom/svg/SVGAElement.cpp
@@ -189,16 +189,19 @@ SVGAElement::IsFocusableInternal(int32_t
{
nsCOMPtr<nsIURI> uri;
if (IsLink(getter_AddRefs(uri))) {
if (aTabIndex) {
*aTabIndex = ((sTabFocusModel & eTabFocus_linksMask) == 0 ? -1 : 0);
}
return true;
}
+ if (nsSVGElement::IsFocusableInternal(aTabIndex, aWithMouse)) {
+ return true;
+ }
if (aTabIndex) {
*aTabIndex = -1;
}
return false;
}
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -605,16 +605,19 @@ nsSVGElement::ParseAttribute(int32_t aNa
rv = transformList->SetBaseValueString(aValue);
if (NS_FAILED(rv)) {
transformList->ClearBaseValue();
} else {
aResult.SetTo(transformList->GetBaseValue(), &aValue);
didSetResult = true;
}
foundMatch = true;
+ } else if (aAttribute == nsGkAtoms::tabindex) {
+ didSetResult = aResult.ParseIntValue(aValue);
+ foundMatch = true;
}
}
if (aAttribute == nsGkAtoms::_class) {
mClassAttribute.SetBaseValue(aValue, this, false);
aResult.ParseAtomArray(aValue);
return true;
}
@@ -1115,16 +1118,29 @@ nsSVGElement::GetViewportElement()
}
already_AddRefed<SVGAnimatedString>
nsSVGElement::ClassName()
{
return mClassAttribute.ToDOMAnimatedString(this);
}
+bool
+nsSVGElement::IsFocusableInternal(int32_t* aTabIndex, bool)
+{
+ int32_t index = TabIndex();
+
+ if (index == -1) {
+ return false;
+ }
+
+ *aTabIndex = index;
+ return true;
+}
+
//------------------------------------------------------------------------
// Helper class: MappedAttrParser, for parsing values of mapped attributes
namespace {
class MOZ_STACK_CLASS MappedAttrParser {
public:
MappedAttrParser(css::Loader* aLoader,
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -312,16 +312,18 @@ public:
virtual void ClearAnyCachedPath() {}
virtual nsIDOMNode* AsDOMNode() final override { return this; }
virtual bool IsTransformable() { return false; }
// WebIDL
mozilla::dom::SVGSVGElement* GetOwnerSVGElement();
nsSVGElement* GetViewportElement();
already_AddRefed<mozilla::dom::SVGAnimatedString> ClassName();
+ virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) override;
+
protected:
virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
#ifdef DEBUG
// We define BeforeSetAttr here and mark it final to ensure it is NOT used
// by SVG elements.
// This is because we're not currently passing the correct value for aValue to
// BeforeSetAttr since it would involve allocating extra SVG value types.
--- a/dom/webidl/SVGElement.webidl
+++ b/dom/webidl/SVGElement.webidl
@@ -16,16 +16,21 @@ interface SVGElement : Element {
[Constant]
readonly attribute SVGAnimatedString className;
[PutForwards=cssText, Constant]
readonly attribute CSSStyleDeclaration style;
readonly attribute SVGSVGElement? ownerSVGElement;
readonly attribute SVGElement? viewportElement;
- attribute EventHandler oncopy;
- attribute EventHandler oncut;
- attribute EventHandler onpaste;
+ attribute EventHandler oncopy;
+ attribute EventHandler oncut;
+ attribute EventHandler onpaste;
+
+ [SetterThrows, Pure]
+ attribute long tabIndex;
+ [Throws] void focus();
+ [Throws] void blur();
};
SVGElement implements GlobalEventHandlers;
SVGElement implements TouchEventHandlers;
SVGElement implements OnErrorEventHandlerForNodes;
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -1704,51 +1704,24 @@ nsXULElement::GetParentTree(nsIDOMXULMul
NS_IMETHODIMP
nsXULElement::Focus()
{
ErrorResult rv;
Focus(rv);
return rv.StealNSResult();
}
-void
-nsXULElement::Focus(ErrorResult& rv)
-{
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- nsCOMPtr<nsIDOMElement> elem = do_QueryObject(this);
- if (fm) {
- rv = fm->SetFocus(this, 0);
- }
-}
-
NS_IMETHODIMP
nsXULElement::Blur()
{
ErrorResult rv;
Blur(rv);
return rv.StealNSResult();
}
-void
-nsXULElement::Blur(ErrorResult& rv)
-{
- if (!ShouldBlur(this))
- return;
-
- nsIDocument* doc = GetComposedDoc();
- if (!doc)
- return;
-
- nsPIDOMWindowOuter* win = doc->GetWindow();
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- if (win && fm) {
- rv = fm->ClearFocus(win);
- }
-}
-
NS_IMETHODIMP
nsXULElement::Click()
{
return ClickWithInputSource(nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN, /* aIsTrusted = */ true);
}
void
nsXULElement::Click(ErrorResult& rv)
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -336,16 +336,18 @@ enum {
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3);
#undef XUL_ELEMENT_FLAG_BIT
class nsXULElement final : public nsStyledElement,
public nsIDOMXULElement
{
public:
+ using Element::Blur;
+ using Element::Focus;
explicit nsXULElement(already_AddRefed<mozilla::dom::NodeInfo> aNodeInfo);
static nsresult
Create(nsXULPrototypeElement* aPrototype, nsIDocument* aDocument,
bool aIsScriptable, bool aIsRoot, mozilla::dom::Element** aResult);
NS_IMPL_FROMCONTENT(nsXULElement, kNameSpaceID_XUL)
@@ -556,18 +558,16 @@ public:
{
return BoolAttrIsTrue(nsGkAtoms::allowevents);
}
already_AddRefed<nsIRDFCompositeDataSource> GetDatabase();
already_AddRefed<nsIXULTemplateBuilder> GetBuilder();
already_AddRefed<nsIRDFResource> GetResource(mozilla::ErrorResult& rv);
nsIControllers* GetControllers(mozilla::ErrorResult& rv);
already_AddRefed<mozilla::dom::BoxObject> GetBoxObject(mozilla::ErrorResult& rv);
- void Focus(mozilla::ErrorResult& rv);
- void Blur(mozilla::ErrorResult& rv);
void Click(mozilla::ErrorResult& rv);
// The XPCOM DoCommand never fails, so it's OK for us.
already_AddRefed<nsINodeList>
GetElementsByAttribute(const nsAString& aAttribute,
const nsAString& aValue);
already_AddRefed<nsINodeList>
GetElementsByAttributeNS(const nsAString& aNamespaceURI,
const nsAString& aAttribute,