mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-06 07:17:30 +09:00
Bug 1373798 - Move HTML dir attribute state into event state flags
* Stop calling SetHasDirAuto/ClearHasDirAuto in input element code * Introduce event state flags that track the state of an element's dir attribute * Rewrite our existing checks for the state of the dir attr on top of the new event state flags * Add pseudo-classes for matching on the dir attribute states * Use the new dir attribute pseudoclasses in html.css Tag #1375
This commit is contained in:
parent
4e14355697
commit
3b2a22f085
11 changed files with 139 additions and 72 deletions
|
|
@ -728,7 +728,7 @@ WalkDescendantsResetAutoDirection(Element* aElement)
|
||||||
{
|
{
|
||||||
nsIContent* child = aElement->GetFirstChild();
|
nsIContent* child = aElement->GetFirstChild();
|
||||||
while (child) {
|
while (child) {
|
||||||
if (child->HasDirAuto()) {
|
if (child->IsElement() && child->AsElement()->HasDirAuto()) {
|
||||||
child = child->GetNextNonChildNode(aElement);
|
child = child->GetNextNonChildNode(aElement);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -791,7 +791,7 @@ WalkDescendantsClearAncestorDirAuto(Element* aElement)
|
||||||
{
|
{
|
||||||
nsIContent* child = aElement->GetFirstChild();
|
nsIContent* child = aElement->GetFirstChild();
|
||||||
while (child) {
|
while (child) {
|
||||||
if (child->HasDirAuto()) {
|
if (child->IsElement() && child->AsElement()->HasDirAuto()) {
|
||||||
child = child->GetNextNonChildNode(aElement);
|
child = child->GetNextNonChildNode(aElement);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -255,6 +255,23 @@ public:
|
||||||
*/
|
*/
|
||||||
void ClearStyleStateLocks();
|
void ClearStyleStateLocks();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessors for the state of our dir attribute.
|
||||||
|
*/
|
||||||
|
bool HasDirAuto() const
|
||||||
|
{
|
||||||
|
return State().HasState(NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Elements with dir="rtl" or dir="ltr".
|
||||||
|
*/
|
||||||
|
bool HasFixedDir() const
|
||||||
|
{
|
||||||
|
return State().HasAtLeastOneOfStates(NS_EVENT_STATE_DIR_ATTR_LTR |
|
||||||
|
NS_EVENT_STATE_DIR_ATTR_RTL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the inline style declaration, if any, for this element.
|
* Get the inline style declaration, if any, for this element.
|
||||||
*/
|
*/
|
||||||
|
|
@ -380,15 +397,6 @@ public:
|
||||||
|
|
||||||
bool GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult);
|
bool GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult);
|
||||||
|
|
||||||
// The bdi element defaults to dir=auto if it has no dir attribute set.
|
|
||||||
// Other elements will only have dir=auto if they have an explicit dir=auto,
|
|
||||||
// which will mean that HasValidDir() returns true but HasFixedDir() returns
|
|
||||||
// false
|
|
||||||
inline bool HasDirAuto() const {
|
|
||||||
return (!HasFixedDir() &&
|
|
||||||
(HasValidDir() || IsHTMLElement(nsGkAtoms::bdi)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Directionality GetComputedDirectionality() const;
|
Directionality GetComputedDirectionality() const;
|
||||||
|
|
||||||
inline Element* GetFlattenedTreeParentElementForStyle() const;
|
inline Element* GetFlattenedTreeParentElementForStyle() const;
|
||||||
|
|
@ -501,6 +509,16 @@ protected:
|
||||||
RemoveStatesSilently(aStates);
|
RemoveStatesSilently(aStates);
|
||||||
NotifyStateChange(aStates);
|
NotifyStateChange(aStates);
|
||||||
}
|
}
|
||||||
|
virtual void ToggleStates(EventStates aStates, bool aNotify)
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
|
||||||
|
"Should only be removing externally-managed states here");
|
||||||
|
mState ^= aStates;
|
||||||
|
if (aNotify) {
|
||||||
|
NotifyStateChange(aStates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void UpdateEditableState(bool aNotify) override;
|
virtual void UpdateEditableState(bool aNotify) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,4 +87,10 @@ nsINode::GetFlattenedTreeParentNodeForStyle() const
|
||||||
return ::GetFlattenedTreeParentNode<nsIContent::eForStyle>(this);
|
return ::GetFlattenedTreeParentNode<nsIContent::eForStyle>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
nsINode::NodeOrAncestorHasDirAuto() const
|
||||||
|
{
|
||||||
|
return AncestorHasDirAuto() || (IsElement() && AsElement()->HasDirAuto());
|
||||||
|
}
|
||||||
|
|
||||||
#endif // nsIContentInlines_h
|
#endif // nsIContentInlines_h
|
||||||
|
|
|
||||||
|
|
@ -1608,10 +1608,11 @@ private:
|
||||||
NodeIsContent,
|
NodeIsContent,
|
||||||
// Set if the node has animations or transitions
|
// Set if the node has animations or transitions
|
||||||
ElementHasAnimations,
|
ElementHasAnimations,
|
||||||
// Set if node has a dir attribute with a valid value (ltr, rtl, or auto)
|
// Set if node has a dir attribute with a valid value (ltr, rtl, or auto).
|
||||||
|
// Note that we cannot compute this from the dir attribute event state
|
||||||
|
// flags, because we can't use those to distinguish
|
||||||
|
// <bdi dir="some-invalid-value"> and <bdi dir="auto">.
|
||||||
NodeHasValidDirAttribute,
|
NodeHasValidDirAttribute,
|
||||||
// Set if node has a dir attribute with a fixed value (ltr or rtl, NOT auto)
|
|
||||||
NodeHasFixedDir,
|
|
||||||
// Set if the node has dir=auto and has a property pointing to the text
|
// Set if the node has dir=auto and has a property pointing to the text
|
||||||
// node that determines its direction
|
// node that determines its direction
|
||||||
NodeHasDirAutoSet,
|
NodeHasDirAutoSet,
|
||||||
|
|
@ -1619,8 +1620,6 @@ private:
|
||||||
// and has a TextNodeDirectionalityMap property listing the elements whose
|
// and has a TextNodeDirectionalityMap property listing the elements whose
|
||||||
// direction it determines.
|
// direction it determines.
|
||||||
NodeHasTextNodeDirectionalityMap,
|
NodeHasTextNodeDirectionalityMap,
|
||||||
// Set if the node has dir=auto.
|
|
||||||
NodeHasDirAuto,
|
|
||||||
// Set if a node in the node's parent chain has dir=auto.
|
// Set if a node in the node's parent chain has dir=auto.
|
||||||
NodeAncestorHasDirAuto,
|
NodeAncestorHasDirAuto,
|
||||||
// Set if the element is in the scope of a scoped style sheet; this flag is
|
// Set if the element is in the scope of a scoped style sheet; this flag is
|
||||||
|
|
@ -1715,17 +1714,6 @@ public:
|
||||||
void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
|
void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
|
||||||
void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
|
void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
|
||||||
bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
|
bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
|
||||||
void SetHasFixedDir() {
|
|
||||||
MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
|
|
||||||
"SetHasFixedDir on text node");
|
|
||||||
SetBoolFlag(NodeHasFixedDir);
|
|
||||||
}
|
|
||||||
void ClearHasFixedDir() {
|
|
||||||
MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
|
|
||||||
"ClearHasFixedDir on text node");
|
|
||||||
ClearBoolFlag(NodeHasFixedDir);
|
|
||||||
}
|
|
||||||
bool HasFixedDir() const { return GetBoolFlag(NodeHasFixedDir); }
|
|
||||||
void SetHasDirAutoSet() {
|
void SetHasDirAutoSet() {
|
||||||
MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
|
MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
|
||||||
"SetHasDirAutoSet on text node");
|
"SetHasDirAutoSet on text node");
|
||||||
|
|
@ -1754,16 +1742,12 @@ public:
|
||||||
return GetBoolFlag(NodeHasTextNodeDirectionalityMap);
|
return GetBoolFlag(NodeHasTextNodeDirectionalityMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHasDirAuto() { SetBoolFlag(NodeHasDirAuto); }
|
|
||||||
void ClearHasDirAuto() { ClearBoolFlag(NodeHasDirAuto); }
|
|
||||||
bool HasDirAuto() const { return GetBoolFlag(NodeHasDirAuto); }
|
|
||||||
|
|
||||||
void SetAncestorHasDirAuto() { SetBoolFlag(NodeAncestorHasDirAuto); }
|
void SetAncestorHasDirAuto() { SetBoolFlag(NodeAncestorHasDirAuto); }
|
||||||
void ClearAncestorHasDirAuto() { ClearBoolFlag(NodeAncestorHasDirAuto); }
|
void ClearAncestorHasDirAuto() { ClearBoolFlag(NodeAncestorHasDirAuto); }
|
||||||
bool AncestorHasDirAuto() const { return GetBoolFlag(NodeAncestorHasDirAuto); }
|
bool AncestorHasDirAuto() const { return GetBoolFlag(NodeAncestorHasDirAuto); }
|
||||||
|
|
||||||
bool NodeOrAncestorHasDirAuto() const
|
// Implemented in nsIContentInlines.h.
|
||||||
{ return HasDirAuto() || AncestorHasDirAuto(); }
|
inline bool NodeOrAncestorHasDirAuto() const;
|
||||||
|
|
||||||
void SetIsElementInStyleScope(bool aValue) {
|
void SetIsElementInStyleScope(bool aValue) {
|
||||||
MOZ_ASSERT(IsElement(), "SetIsInStyleScope on a non-Element node");
|
MOZ_ASSERT(IsElement(), "SetIsInStyleScope on a non-Element node");
|
||||||
|
|
|
||||||
|
|
@ -292,14 +292,40 @@ private:
|
||||||
#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(43)
|
#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(43)
|
||||||
// Element is highlighted (devtools inspector)
|
// Element is highlighted (devtools inspector)
|
||||||
#define NS_EVENT_STATE_DEVTOOLS_HIGHLIGHTED NS_DEFINE_EVENT_STATE_MACRO(45)
|
#define NS_EVENT_STATE_DEVTOOLS_HIGHLIGHTED NS_DEFINE_EVENT_STATE_MACRO(45)
|
||||||
|
// States for tracking the state of the "dir" attribute for HTML elements. We
|
||||||
|
// use these to avoid having to get "dir" attributes all the time during
|
||||||
|
// selector matching for some parts of the UA stylesheet.
|
||||||
|
//
|
||||||
|
// These states are externally managed, because we also don't want to keep
|
||||||
|
// getting "dir" attributes in IntrinsicState.
|
||||||
|
//
|
||||||
|
// Element is HTML and has a "dir" attibute. This state might go away depending
|
||||||
|
// on how https://github.com/whatwg/html/issues/2769 gets resolved. The value
|
||||||
|
// could be anything.
|
||||||
|
#define NS_EVENT_STATE_HAS_DIR_ATTR NS_DEFINE_EVENT_STATE_MACRO(46)
|
||||||
|
// Element is HTML, has a "dir" attribute, and the attribute's value is
|
||||||
|
// case-insensitively equal to "ltr".
|
||||||
|
#define NS_EVENT_STATE_DIR_ATTR_LTR NS_DEFINE_EVENT_STATE_MACRO(47)
|
||||||
|
// Element is HTML, has a "dir" attribute, and the attribute's value is
|
||||||
|
// case-insensitively equal to "rtl".
|
||||||
|
#define NS_EVENT_STATE_DIR_ATTR_RTL NS_DEFINE_EVENT_STATE_MACRO(48)
|
||||||
|
// Element is HTML, and is either a <bdi> element with no valid-valued "dir"
|
||||||
|
// attribute or any HTML element which has a "dir" attribute whose value is
|
||||||
|
// "auto".
|
||||||
|
#define NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO NS_DEFINE_EVENT_STATE_MACRO(49)
|
||||||
// Element is an unresolved custom element candidate
|
// Element is an unresolved custom element candidate
|
||||||
#define NS_EVENT_STATE_UNRESOLVED NS_DEFINE_EVENT_STATE_MACRO(46)
|
#define NS_EVENT_STATE_UNRESOLVED NS_DEFINE_EVENT_STATE_MACRO(50)
|
||||||
// Element is transitioning for rules changed by style editor
|
// Element is transitioning for rules changed by style editor
|
||||||
#define NS_EVENT_STATE_STYLEEDITOR_TRANSITIONING NS_DEFINE_EVENT_STATE_MACRO(47)
|
#define NS_EVENT_STATE_STYLEEDITOR_TRANSITIONING NS_DEFINE_EVENT_STATE_MACRO(51)
|
||||||
// Content shows its placeholder
|
// Content shows its placeholder
|
||||||
#define NS_EVENT_STATE_PLACEHOLDERSHOWN NS_DEFINE_EVENT_STATE_MACRO(48)
|
#define NS_EVENT_STATE_PLACEHOLDERSHOWN NS_DEFINE_EVENT_STATE_MACRO(52)
|
||||||
// Element has focus-within.
|
// Element has focus-within.
|
||||||
#define NS_EVENT_STATE_FOCUS_WITHIN NS_DEFINE_EVENT_STATE_MACRO(49)
|
#define NS_EVENT_STATE_FOCUS_WITHIN NS_DEFINE_EVENT_STATE_MACRO(53)
|
||||||
|
|
||||||
|
#define DIR_ATTR_STATES (NS_EVENT_STATE_HAS_DIR_ATTR | \
|
||||||
|
NS_EVENT_STATE_DIR_ATTR_LTR | \
|
||||||
|
NS_EVENT_STATE_DIR_ATTR_RTL | \
|
||||||
|
NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO)
|
||||||
|
|
||||||
// Event state that is used for values that need to be parsed but do nothing.
|
// Event state that is used for values that need to be parsed but do nothing.
|
||||||
#define NS_EVENT_STATE_IGNORE NS_DEFINE_EVENT_STATE_MACRO(63)
|
#define NS_EVENT_STATE_IGNORE NS_DEFINE_EVENT_STATE_MACRO(63)
|
||||||
|
|
@ -310,7 +336,7 @@ private:
|
||||||
|
|
||||||
#define DIRECTION_STATES (NS_EVENT_STATE_LTR | NS_EVENT_STATE_RTL)
|
#define DIRECTION_STATES (NS_EVENT_STATE_LTR | NS_EVENT_STATE_RTL)
|
||||||
|
|
||||||
#define ESM_MANAGED_STATES (NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS | \
|
#define ESM_MANAGED_STATES (DIR_ATTR_STATES | NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS | \
|
||||||
NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER | \
|
NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER | \
|
||||||
NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
|
NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
|
||||||
NS_EVENT_STATE_FULL_SCREEN | NS_EVENT_STATE_UNRESOLVED | \
|
NS_EVENT_STATE_FULL_SCREEN | NS_EVENT_STATE_UNRESOLVED | \
|
||||||
|
|
|
||||||
|
|
@ -1264,10 +1264,6 @@ HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
}
|
}
|
||||||
} else if (aNotify && aName == nsGkAtoms::disabled) {
|
} else if (aNotify && aName == nsGkAtoms::disabled) {
|
||||||
mDisabledChanged = true;
|
mDisabledChanged = true;
|
||||||
} else if (aName == nsGkAtoms::dir &&
|
|
||||||
AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
|
|
||||||
nsGkAtoms::_auto, eIgnoreCase)) {
|
|
||||||
SetDirectionIfAuto(false, aNotify);
|
|
||||||
} else if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
|
} else if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
|
||||||
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
|
||||||
|
|
||||||
|
|
@ -1419,7 +1415,7 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
"HTML5 spec does not allow underflow for type=range");
|
"HTML5 spec does not allow underflow for type=range");
|
||||||
} else if (aName == nsGkAtoms::dir &&
|
} else if (aName == nsGkAtoms::dir &&
|
||||||
aValue && aValue->Equals(nsGkAtoms::_auto, eIgnoreCase)) {
|
aValue && aValue->Equals(nsGkAtoms::_auto, eIgnoreCase)) {
|
||||||
SetDirectionIfAuto(true, aNotify);
|
SetDirectionFromValue(aNotify);
|
||||||
} else if (aName == nsGkAtoms::lang) {
|
} else if (aName == nsGkAtoms::lang) {
|
||||||
if (mType == NS_FORM_INPUT_NUMBER) {
|
if (mType == NS_FORM_INPUT_NUMBER) {
|
||||||
// Update the value that is displayed to the user to the new locale:
|
// Update the value that is displayed to the user to the new locale:
|
||||||
|
|
@ -4975,7 +4971,9 @@ HTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set direction based on value if dir=auto
|
// Set direction based on value if dir=auto
|
||||||
SetDirectionIfAuto(HasDirAuto(), false);
|
if (HasDirAuto()) {
|
||||||
|
SetDirectionFromValue(false);
|
||||||
|
}
|
||||||
|
|
||||||
// An element can't suffer from value missing if it is not in a document.
|
// An element can't suffer from value missing if it is not in a document.
|
||||||
// We have to check if we suffer from that as we are now in a document.
|
// We have to check if we suffer from that as we are now in a document.
|
||||||
|
|
@ -6693,18 +6691,13 @@ HTMLInputElement::SetDefaultValueAsValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HTMLInputElement::SetDirectionIfAuto(bool aAuto, bool aNotify)
|
HTMLInputElement::SetDirectionFromValue(bool aNotify)
|
||||||
{
|
{
|
||||||
if (aAuto) {
|
|
||||||
SetHasDirAuto();
|
|
||||||
if (IsSingleLineTextControl(true)) {
|
if (IsSingleLineTextControl(true)) {
|
||||||
nsAutoString value;
|
nsAutoString value;
|
||||||
GetValue(value);
|
GetValue(value);
|
||||||
SetDirectionalityFromValue(this, value, aNotify);
|
SetDirectionalityFromValue(this, value, aNotify);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
ClearHasDirAuto();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
@ -8480,7 +8473,7 @@ HTMLInputElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
|
||||||
UpdateAllValidityStates(aNotify);
|
UpdateAllValidityStates(aNotify);
|
||||||
|
|
||||||
if (HasDirAuto()) {
|
if (HasDirAuto()) {
|
||||||
SetDirectionIfAuto(true, aNotify);
|
SetDirectionFromValue(aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
// :placeholder-shown pseudo-class may change when the value changes.
|
// :placeholder-shown pseudo-class may change when the value changes.
|
||||||
|
|
|
||||||
|
|
@ -1122,7 +1122,7 @@ protected:
|
||||||
*/
|
*/
|
||||||
nsresult SetDefaultValueAsValue();
|
nsresult SetDefaultValueAsValue();
|
||||||
|
|
||||||
virtual void SetDirectionIfAuto(bool aAuto, bool aNotify);
|
void SetDirectionFromValue(bool aNotify);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return if an element should have a specific validity UI
|
* Return if an element should have a specific validity UI
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#define mozilla_dom_HTMLUnknownElement_h
|
#define mozilla_dom_HTMLUnknownElement_h
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/EventStates.h"
|
||||||
#include "nsGenericHTMLElement.h"
|
#include "nsGenericHTMLElement.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
@ -27,7 +28,7 @@ public:
|
||||||
: nsGenericHTMLElement(aNodeInfo)
|
: nsGenericHTMLElement(aNodeInfo)
|
||||||
{
|
{
|
||||||
if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
|
if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
|
||||||
SetHasDirAuto();
|
AddStatesSilently(NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -708,28 +708,49 @@ nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
||||||
}
|
}
|
||||||
else if (aName == nsGkAtoms::dir) {
|
else if (aName == nsGkAtoms::dir) {
|
||||||
Directionality dir = eDir_LTR;
|
Directionality dir = eDir_LTR;
|
||||||
|
// A boolean tracking whether we need to recompute our directionality.
|
||||||
|
// This needs to happen after we update our internal "dir" attribute
|
||||||
|
// state but before we call SetDirectionalityOnDescendants.
|
||||||
|
bool recomputeDirectionality = false;
|
||||||
|
// We don't want to have to keep getting the "dir" attribute in
|
||||||
|
// IntrinsicState, so we manually recompute our dir-related event states
|
||||||
|
// here and send the relevant update notifications.
|
||||||
|
EventStates dirStates;
|
||||||
if (aValue && aValue->Type() == nsAttrValue::eEnum) {
|
if (aValue && aValue->Type() == nsAttrValue::eEnum) {
|
||||||
SetHasValidDir();
|
SetHasValidDir();
|
||||||
|
dirStates |= NS_EVENT_STATE_HAS_DIR_ATTR;
|
||||||
Directionality dirValue = (Directionality)aValue->GetEnumValue();
|
Directionality dirValue = (Directionality)aValue->GetEnumValue();
|
||||||
if (dirValue == eDir_Auto) {
|
if (dirValue == eDir_Auto) {
|
||||||
SetHasDirAuto();
|
dirStates |= NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO;
|
||||||
ClearHasFixedDir();
|
|
||||||
} else {
|
} else {
|
||||||
dir = dirValue;
|
dir = dirValue;
|
||||||
SetDirectionality(dir, aNotify);
|
SetDirectionality(dir, aNotify);
|
||||||
ClearHasDirAuto();
|
if (dirValue == eDir_LTR) {
|
||||||
SetHasFixedDir();
|
dirStates |= NS_EVENT_STATE_DIR_ATTR_LTR;
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(dirValue == eDir_RTL);
|
||||||
|
dirStates |= NS_EVENT_STATE_DIR_ATTR_RTL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (aValue) {
|
||||||
|
// We have a value, just not a valid one.
|
||||||
|
dirStates |= NS_EVENT_STATE_HAS_DIR_ATTR;
|
||||||
|
}
|
||||||
ClearHasValidDir();
|
ClearHasValidDir();
|
||||||
ClearHasFixedDir();
|
|
||||||
if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
|
if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
|
||||||
SetHasDirAuto();
|
dirStates |= NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO;
|
||||||
} else {
|
} else {
|
||||||
ClearHasDirAuto();
|
recomputeDirectionality = true;
|
||||||
dir = RecomputeDirectionality(this, aNotify);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Now figure out what's changed about our dir states.
|
||||||
|
EventStates oldDirStates = State() & DIR_ATTR_STATES;
|
||||||
|
EventStates changedStates = dirStates ^ oldDirStates;
|
||||||
|
ToggleStates(changedStates, aNotify);
|
||||||
|
if (recomputeDirectionality) {
|
||||||
|
dir = RecomputeDirectionality(this, aNotify);
|
||||||
|
}
|
||||||
SetDirectionalityOnDescendants(this, dir, aNotify);
|
SetDirectionalityOnDescendants(this, dir, aNotify);
|
||||||
} else if (aName == nsGkAtoms::contenteditable) {
|
} else if (aName == nsGkAtoms::contenteditable) {
|
||||||
int32_t editableCountDelta = 0;
|
int32_t editableCountDelta = 0;
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,19 @@ CSS_STATE_PSEUDO_CLASS(mozMathIncrementScriptLevel,
|
||||||
":-moz-math-increment-script-level", 0, "",
|
":-moz-math-increment-script-level", 0, "",
|
||||||
NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL)
|
NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL)
|
||||||
|
|
||||||
|
CSS_STATE_PSEUDO_CLASS(mozHasDirAttr, ":-moz-has-dir-attr",
|
||||||
|
CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
|
||||||
|
NS_EVENT_STATE_HAS_DIR_ATTR)
|
||||||
|
CSS_STATE_PSEUDO_CLASS(mozDirAttrLTR, ":-moz-dir-attr-ltr",
|
||||||
|
CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
|
||||||
|
NS_EVENT_STATE_DIR_ATTR_LTR)
|
||||||
|
CSS_STATE_PSEUDO_CLASS(mozDirAttrRTL, ":-moz-dir-attr-rtl",
|
||||||
|
CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
|
||||||
|
NS_EVENT_STATE_DIR_ATTR_RTL)
|
||||||
|
CSS_STATE_PSEUDO_CLASS(mozDirAttrLikeAuto, ":-moz-dir-attr-like-auto",
|
||||||
|
CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
|
||||||
|
NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO)
|
||||||
|
|
||||||
// CSS 3 UI
|
// CSS 3 UI
|
||||||
// http://www.w3.org/TR/2004/CR-css3-ui-20040511/#pseudo-classes
|
// http://www.w3.org/TR/2004/CR-css3-ui-20040511/#pseudo-classes
|
||||||
CSS_STATE_PSEUDO_CLASS(required, ":required", 0, "", NS_EVENT_STATE_REQUIRED)
|
CSS_STATE_PSEUDO_CLASS(required, ":required", 0, "", NS_EVENT_STATE_REQUIRED)
|
||||||
|
|
|
||||||
|
|
@ -7,18 +7,18 @@
|
||||||
|
|
||||||
/* bidi */
|
/* bidi */
|
||||||
|
|
||||||
[dir] {
|
:-moz-has-dir-attr {
|
||||||
unicode-bidi: isolate;
|
unicode-bidi: isolate;
|
||||||
}
|
}
|
||||||
[dir="rtl"] {
|
:-moz-dir-attr-rtl {
|
||||||
direction: rtl;
|
direction: rtl;
|
||||||
}
|
}
|
||||||
[dir="ltr"] {
|
:-moz-dir-attr-ltr {
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdi:dir(ltr), [dir="auto"]:dir(ltr) { direction: ltr; }
|
:-moz-dir-attr-like-auto:dir(ltr) { direction: ltr; }
|
||||||
bdi:dir(rtl), [dir="auto"]:dir(rtl) { direction: rtl; }
|
:-moz-dir-attr-like-auto:dir(rtl) { direction: rtl; }
|
||||||
|
|
||||||
/* To ensure http://www.w3.org/TR/REC-html40/struct/dirlang.html#style-bidi:
|
/* To ensure http://www.w3.org/TR/REC-html40/struct/dirlang.html#style-bidi:
|
||||||
*
|
*
|
||||||
|
|
@ -89,10 +89,15 @@ xmp {
|
||||||
bdi, output {
|
bdi, output {
|
||||||
unicode-bidi: isolate;
|
unicode-bidi: isolate;
|
||||||
}
|
}
|
||||||
bdo, bdo[dir] {
|
/* We need the "bdo:-moz-has-dir-attr" bit because "bdo" has lower
|
||||||
|
specificity than the ":-moz-has-dir-attr" selector above. */
|
||||||
|
bdo, bdo:-moz-has-dir-attr {
|
||||||
unicode-bidi: isolate-override;
|
unicode-bidi: isolate-override;
|
||||||
}
|
}
|
||||||
textarea[dir="auto"], pre[dir="auto"] { unicode-bidi: plaintext; }
|
textarea:-moz-dir-attr-like-auto,
|
||||||
|
pre:-moz-dir-attr-like-auto {
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
/* blocks */
|
/* blocks */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue