mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Add support for :dir(ltr/rtl) CSS selector, layout/style part. Bug 562159, r=bz
This commit is contained in:
parent
4a67200814
commit
1c6ba0a43d
@ -248,6 +248,10 @@ private:
|
||||
#define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(41)
|
||||
// Platform does not support plugin content (some mobile platforms)
|
||||
#define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(42)
|
||||
// Element is ltr (for :dir pseudo-class)
|
||||
#define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(43)
|
||||
// Element is rtl (for :dir pseudo-class)
|
||||
#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(44)
|
||||
|
||||
/**
|
||||
* NOTE: do not go over 63 without updating nsEventStates::InternalType!
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
{
|
||||
NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
|
||||
"Unexpected namespace");
|
||||
AddStatesSilently(NS_EVENT_STATE_LTR);
|
||||
}
|
||||
|
||||
/** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/
|
||||
|
@ -114,6 +114,7 @@ PEMQExpectedFeatureValue=Found invalid value for media feature.
|
||||
PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'.
|
||||
PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'.
|
||||
PEAnonBoxNotAlone=Did not expect anonymous box.
|
||||
PEBadDirValue=Expected 'ltr' or 'rtl' in direction selector but found '%1$S'.
|
||||
PESupportsConditionStartEOF='not' or '('
|
||||
PESupportsConditionInParensStartEOF='not', '(' or identifier
|
||||
PESupportsConditionNotEOF='not'
|
||||
|
@ -3595,10 +3595,12 @@ CSSParserImpl::ParsePseudoClassWithIdentArg(nsCSSSelector& aSelector,
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
|
||||
// -moz-locale-dir can only have values of 'ltr' or 'rtl'.
|
||||
if (aType == nsCSSPseudoClasses::ePseudoClass_mozLocaleDir) {
|
||||
// -moz-locale-dir and :dir can only have values of 'ltr' or 'rtl'.
|
||||
if (aType == nsCSSPseudoClasses::ePseudoClass_mozLocaleDir ||
|
||||
aType == nsCSSPseudoClasses::ePseudoClass_dir) {
|
||||
if (!mToken.mIdent.EqualsLiteral("ltr") &&
|
||||
!mToken.mIdent.EqualsLiteral("rtl")) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEBadDirValue);
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
}
|
||||
|
@ -9,27 +9,45 @@
|
||||
* This file contains the list of nsIAtoms and their values for CSS
|
||||
* pseudo-classes. It is designed to be used as inline input to
|
||||
* nsCSSPseudoClasses.cpp *only* through the magic of C preprocessing.
|
||||
* All entries must be enclosed in the macros CSS_PSEUDO_CLASS or
|
||||
* CSS_STATE_PSEUDO_CLASS which will have cruel and unusual things
|
||||
* done to it. The entries should be kept in some sort of logical
|
||||
* order. The first argument to CSS_PSEUDO_CLASS is the C++
|
||||
* identifier of the atom. The second argument is the string value of
|
||||
* the atom. CSS_STATE_PSEUDO_CLASS also takes the name of the state
|
||||
* bits that the class corresponds to. Only one of the bits needs to
|
||||
* match for the pseudo-class to match. If CSS_STATE_PSEUDO_CLASS is
|
||||
* not defined, it'll be automatically defined to CSS_PSEUDO_CLASS.
|
||||
* All entries must be enclosed in the macros CSS_PSEUDO_CLASS,
|
||||
* CSS_STATE_DEPENDENT_PSEUDO_CLASS, or CSS_STATE_PSEUDO_CLASS which
|
||||
* will have cruel and unusual things done to them. The entries should
|
||||
* be kept in some sort of logical order. The first argument to
|
||||
* CSS_PSEUDO_CLASS is the C++ identifier of the atom. The second
|
||||
* argument is the string value of the atom.
|
||||
* CSS_STATE_DEPENDENT_PSEUDO_CLASS and CSS_STATE_PSEUDO_CLASS also take
|
||||
* the name of the state bits that the class corresponds to. Only one
|
||||
* of the bits needs to match for a CSS_STATE_PSEUDO_CLASS to match;
|
||||
* CSS_STATE_DEPENDENT_PSEUDO_CLASS matching depends on a customized per-class
|
||||
* algorithm which should be defined in SelectorMatches() in
|
||||
* nsCSSRuleProcessor.cpp.
|
||||
*
|
||||
* If CSS_STATE_PSEUDO_CLASS is not defined, it'll be automatically
|
||||
* defined to CSS_STATE_DEPENDENT_PSEUDO_CLASS;
|
||||
* if CSS_STATE_DEPENDENT_PSEUDO_CLASS is not defined, it'll be
|
||||
* automatically defined to CSS_PSEUDO_CLASS.
|
||||
*/
|
||||
|
||||
// OUTPUT_CLASS=nsCSSPseudoClasses
|
||||
// MACRO_NAME=CSS_PSEUDO_CLASS
|
||||
|
||||
#ifdef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||
#error "CSS_STATE_DEPENDENT_PSEUDO_CLASS shouldn't be defined"
|
||||
#endif
|
||||
|
||||
#ifndef CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||
#define CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _bit) \
|
||||
CSS_PSEUDO_CLASS(_name, _value)
|
||||
#define DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||
#endif
|
||||
|
||||
#ifdef DEFINED_CSS_STATE_PSEUDO_CLASS
|
||||
#error "This shouldn't be defined"
|
||||
#error "CSS_STATE_PSEUDO_CLASS shouldn't be defined"
|
||||
#endif
|
||||
|
||||
#ifndef CSS_STATE_PSEUDO_CLASS
|
||||
#define CSS_STATE_PSEUDO_CLASS(_name, _value, _bit) \
|
||||
CSS_PSEUDO_CLASS(_name, _value)
|
||||
CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _bit)
|
||||
#define DEFINED_CSS_STATE_PSEUDO_CLASS
|
||||
#endif
|
||||
|
||||
@ -90,6 +108,11 @@ CSS_PSEUDO_CLASS(mozTableBorderNonzero, ":-moz-table-border-nonzero")
|
||||
// it doesn't actually get directly matched on in SelectorMatches.
|
||||
CSS_PSEUDO_CLASS(notPseudo, ":not")
|
||||
|
||||
// :dir(ltr) and :dir(rtl) match elements whose resolved directionality
|
||||
// in the markup language is ltr or rtl respectively
|
||||
CSS_STATE_DEPENDENT_PSEUDO_CLASS(dir, ":dir",
|
||||
NS_EVENT_STATE_LTR | NS_EVENT_STATE_RTL)
|
||||
|
||||
CSS_STATE_PSEUDO_CLASS(link, ":link", NS_EVENT_STATE_UNVISITED)
|
||||
// what matches :link or :visited
|
||||
CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link",
|
||||
@ -178,3 +201,8 @@ CSS_STATE_PSEUDO_CLASS(mozMeterSubSubOptimum, ":-moz-meter-sub-sub-optimum",
|
||||
#undef DEFINED_CSS_STATE_PSEUDO_CLASS
|
||||
#undef CSS_STATE_PSEUDO_CLASS
|
||||
#endif
|
||||
|
||||
#ifdef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||
#undef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||
#undef CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||
#endif
|
||||
|
@ -42,7 +42,8 @@ nsCSSPseudoClasses::HasStringArg(Type aType)
|
||||
return aType == ePseudoClass_lang ||
|
||||
aType == ePseudoClass_mozEmptyExceptChildrenWithLocalname ||
|
||||
aType == ePseudoClass_mozSystemMetric ||
|
||||
aType == ePseudoClass_mozLocaleDir;
|
||||
aType == ePseudoClass_mozLocaleDir ||
|
||||
aType == ePseudoClass_dir;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1308,7 +1308,7 @@ struct NodeMatchContext {
|
||||
// event-state-dependent selector for any value of that event state.
|
||||
// So mStateMask contains the states that should NOT be tested.
|
||||
//
|
||||
// NOTE: For |aStateMask| to work correctly, it's important that any
|
||||
// NOTE: For |mStateMask| to work correctly, it's important that any
|
||||
// change that changes multiple state bits include all those state
|
||||
// bits in the notification. Otherwise, if multiple states change but
|
||||
// we do separate notifications then we might determine the style is
|
||||
@ -1533,7 +1533,21 @@ checkGenericEmptyMatches(Element* aElement,
|
||||
return (child == nullptr);
|
||||
}
|
||||
|
||||
// An array of the states that are relevant for various pseudoclasses.
|
||||
// Arrays of the states that are relevant for various pseudoclasses.
|
||||
static const nsEventStates sPseudoClassStateDependences[] = {
|
||||
#define CSS_PSEUDO_CLASS(_name, _value) \
|
||||
nsEventStates(),
|
||||
#define CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _states) \
|
||||
_states,
|
||||
#include "nsCSSPseudoClassList.h"
|
||||
#undef CSS_STATE_DEPENDENT_PSEUDO_CLASS
|
||||
#undef CSS_PSEUDO_CLASS
|
||||
// Add more entries for our fake values to make sure we can't
|
||||
// index out of bounds into this array no matter what.
|
||||
nsEventStates(),
|
||||
nsEventStates()
|
||||
};
|
||||
|
||||
static const nsEventStates sPseudoClassStates[] = {
|
||||
#define CSS_PSEUDO_CLASS(_name, _value) \
|
||||
nsEventStates(),
|
||||
@ -1556,7 +1570,7 @@ MOZ_STATIC_ASSERT(NS_ARRAY_LENGTH(sPseudoClassStates) ==
|
||||
// * when non-null, it indicates that we're processing a negation,
|
||||
// which is done only when SelectorMatches calls itself recursively
|
||||
// * what it points to should be set to true whenever a test is skipped
|
||||
// because of aStateMask
|
||||
// because of aNodeMatchContent.mStateMask
|
||||
static bool SelectorMatches(Element* aElement,
|
||||
nsCSSSelector* aSelector,
|
||||
NodeMatchContext& aNodeMatchContext,
|
||||
@ -1997,6 +2011,38 @@ static bool SelectorMatches(Element* aElement,
|
||||
}
|
||||
break;
|
||||
|
||||
case nsCSSPseudoClasses::ePseudoClass_dir:
|
||||
{
|
||||
if (aDependence) {
|
||||
nsEventStates states
|
||||
= sPseudoClassStateDependences[pseudoClass->mType];
|
||||
if (aNodeMatchContext.mStateMask.HasAtLeastOneOfStates(states)) {
|
||||
*aDependence = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// if we only had to consider HTML, directionality would be exclusively
|
||||
// LTR or RTL, and this could be just
|
||||
//
|
||||
// if (dirString.EqualsLiteral("rtl") !=
|
||||
// aElement->StyleState().HasState(NS_EVENT_STATE_RTL)
|
||||
//
|
||||
// However, in markup languages where there is no direction attribute
|
||||
// we have to consider the possibility that neither dir(rtl) nor
|
||||
// dir(ltr) matches.
|
||||
nsEventStates state = aElement->StyleState();
|
||||
bool elementIsRTL = state.HasState(NS_EVENT_STATE_RTL);
|
||||
bool elementIsLTR = state.HasState(NS_EVENT_STATE_LTR);
|
||||
nsDependentString dirString(pseudoClass->u.mString);
|
||||
|
||||
if ((dirString.EqualsLiteral("rtl") && !elementIsRTL) ||
|
||||
(dirString.EqualsLiteral("ltr") && !elementIsLTR)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(false, "How did that happen?");
|
||||
}
|
||||
@ -2128,10 +2174,10 @@ static bool SelectorMatches(Element* aElement,
|
||||
bool dependence = false;
|
||||
result = !SelectorMatches(aElement, negation, aNodeMatchContext,
|
||||
aTreeMatchContext, &dependence);
|
||||
// If the selector does match due to the dependence on aStateMask,
|
||||
// then we want to keep result true so that the final result of
|
||||
// SelectorMatches is true. Doing so tells StateEnumFunc that
|
||||
// there is a dependence on the state.
|
||||
// If the selector does match due to the dependence on
|
||||
// aNodeMatchContext.mStateMask, then we want to keep result true
|
||||
// so that the final result of SelectorMatches is true. Doing so
|
||||
// tells StateEnumFunc that there is a dependence on the state.
|
||||
result = result || dependence;
|
||||
}
|
||||
}
|
||||
@ -2665,7 +2711,7 @@ nsEventStates ComputeSelectorStateDependence(nsCSSSelector& aSelector)
|
||||
if (pseudoClass->mType >= nsCSSPseudoClasses::ePseudoClass_Count) {
|
||||
continue;
|
||||
}
|
||||
states |= sPseudoClassStates[pseudoClass->mType];
|
||||
states |= sPseudoClassStateDependences[pseudoClass->mType];
|
||||
}
|
||||
return states;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user