diff --git a/servo/components/style/build_gecko.rs b/servo/components/style/build_gecko.rs index 2eec1be1ce33..2b75121f1d04 100644 --- a/servo/components/style/build_gecko.rs +++ b/servo/components/style/build_gecko.rs @@ -254,6 +254,7 @@ mod bindings { "mozilla::ServoStyleSheet", "mozilla::ServoElementSnapshot.*", "mozilla::ConsumeStyleBehavior", + "mozilla::CSSPseudoClassType", "mozilla::css::SheetParsingMode", "mozilla::TraversalRootBehavior", "mozilla::DisplayItemClip", // Needed because bindgen generates @@ -472,6 +473,7 @@ mod bindings { "ThreadSafeURIHolder", "ThreadSafePrincipalHolder", "ConsumeStyleBehavior", + "CSSPseudoClassType", "TraversalRootBehavior", "FontFamilyList", "FontFamilyType", diff --git a/servo/components/style/gecko/selector_parser.rs b/servo/components/style/gecko/selector_parser.rs index 44ea037ef622..80a8736adadf 100644 --- a/servo/components/style/gecko/selector_parser.rs +++ b/servo/components/style/gecko/selector_parser.rs @@ -6,6 +6,7 @@ use cssparser::ToCss; use element_state::ElementState; +use gecko_bindings::structs::CSSPseudoClassType; use selector_parser::{SelectorParser, PseudoElementCascadeType}; use selector_parser::{attr_equals_selector_is_shareable, attr_exists_selector_is_shareable}; use selectors::parser::AttrSelector; @@ -153,6 +154,10 @@ pub enum NonTSPseudoClass { ReadWrite, /// :read-only ReadOnly, + + // Internal pseudo-classes + /// :-moz-browser-frame + MozBrowserFrame, } impl ToCss for NonTSPseudoClass { @@ -172,11 +177,35 @@ impl ToCss for NonTSPseudoClass { Indeterminate => ":indeterminate", ReadWrite => ":read-write", ReadOnly => ":read-only", + + MozBrowserFrame => ":-moz-browser-frame", }) } } impl NonTSPseudoClass { + /// A pseudo-class is internal if it can only be used inside + /// user agent style sheets. + pub fn is_internal(&self) -> bool { + use self::NonTSPseudoClass::*; + match *self { + AnyLink | + Link | + Visited | + Active | + Focus | + Fullscreen | + Hover | + Enabled | + Disabled | + Checked | + Indeterminate | + ReadWrite | + ReadOnly => false, + MozBrowserFrame => true, + } + } + /// Get the state flag associated with a pseudo-class, if any. pub fn state_flag(&self) -> ElementState { use element_state::*; @@ -194,9 +223,31 @@ impl NonTSPseudoClass { AnyLink | Link | - Visited => ElementState::empty(), + Visited | + MozBrowserFrame => ElementState::empty(), } } + + /// Convert NonTSPseudoClass to Gecko's CSSPseudoClassType. + pub fn to_gecko_pseudoclasstype(&self) -> Option { + use gecko_bindings::structs::CSSPseudoClassType::*; + use self::NonTSPseudoClass::*; + Some(match *self { + AnyLink => anyLink, + Link => link, + Visited => visited, + Active => active, + Focus => focus, + Fullscreen => fullscreen, + Hover => hover, + Enabled => enabled, + Disabled => disabled, + Checked => checked, + Indeterminate => indeterminate, + MozBrowserFrame => mozBrowserFrame, + ReadWrite | ReadOnly => { return None; } + }) + } } /// The dummy struct we use to implement our selector parsing. @@ -245,10 +296,18 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> { "indeterminate" => Indeterminate, "read-write" => ReadWrite, "read-only" => ReadOnly, + + // Internal + "-moz-browser-frame" => MozBrowserFrame, + _ => return Err(()) }; - Ok(pseudo_class) + if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() { + Ok(pseudo_class) + } else { + Err(()) + } } fn parse_pseudo_element(&self, name: Cow) -> Result { diff --git a/servo/components/style/gecko/wrapper.rs b/servo/components/style/gecko/wrapper.rs index f5890e2b95f4..8b74844590bc 100644 --- a/servo/components/style/gecko/wrapper.rs +++ b/servo/components/style/gecko/wrapper.rs @@ -26,7 +26,7 @@ use gecko_bindings::bindings; use gecko_bindings::bindings::{Gecko_DropStyleChildrenIterator, Gecko_MaybeCreateStyleChildrenIterator}; use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetLastChild, Gecko_GetNextStyleChild}; use gecko_bindings::bindings::{Gecko_GetServoDeclarationBlock, Gecko_IsHTMLElementInHTMLDocument}; -use gecko_bindings::bindings::{Gecko_IsLink, Gecko_IsRootElement}; +use gecko_bindings::bindings::{Gecko_IsLink, Gecko_IsRootElement, Gecko_MatchesElement}; use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink, Gecko_Namespace}; use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags}; use gecko_bindings::bindings::Gecko_ClassOrClassList; @@ -519,6 +519,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { NonTSPseudoClass::ReadOnly => { !self.get_state().contains(pseudo_class.state_flag()) } + + NonTSPseudoClass::MozBrowserFrame => unsafe { + Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0) + } } } diff --git a/servo/components/style/gecko_bindings/bindings.rs b/servo/components/style/gecko_bindings/bindings.rs index d9106d9ace2b..a9b73f54e8f2 100644 --- a/servo/components/style/gecko_bindings/bindings.rs +++ b/servo/components/style/gecko_bindings/bindings.rs @@ -10,6 +10,7 @@ use gecko_bindings::structs::RawGeckoPresContext; use gecko_bindings::structs::ThreadSafeURIHolder; use gecko_bindings::structs::ThreadSafePrincipalHolder; use gecko_bindings::structs::ConsumeStyleBehavior; +use gecko_bindings::structs::CSSPseudoClassType; use gecko_bindings::structs::TraversalRootBehavior; use gecko_bindings::structs::FontFamilyList; use gecko_bindings::structs::FontFamilyType; @@ -370,6 +371,10 @@ extern "C" { extern "C" { pub fn Gecko_IsRootElement(element: RawGeckoElementBorrowed) -> bool; } +extern "C" { + pub fn Gecko_MatchesElement(type_: CSSPseudoClassType, + element: RawGeckoElementBorrowed) -> bool; +} extern "C" { pub fn Gecko_LocalName(element: RawGeckoElementBorrowed) -> *mut nsIAtom; } diff --git a/servo/components/style/gecko_bindings/structs_debug.rs b/servo/components/style/gecko_bindings/structs_debug.rs index 25ed0cb366f2..4c8b3956b937 100644 --- a/servo/components/style/gecko_bindings/structs_debug.rs +++ b/servo/components/style/gecko_bindings/structs_debug.rs @@ -3204,6 +3204,93 @@ pub mod root { root::mozilla::StyleShapeSource; pub type StyleShapeOutside = root::mozilla::StyleShapeSource; + #[repr(u8)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum CSSPseudoClassType { + empty = 0, + mozOnlyWhitespace = 1, + mozEmptyExceptChildrenWithLocalname = 2, + lang = 3, + mozBoundElement = 4, + root = 5, + any = 6, + firstChild = 7, + firstNode = 8, + lastChild = 9, + lastNode = 10, + onlyChild = 11, + firstOfType = 12, + lastOfType = 13, + onlyOfType = 14, + nthChild = 15, + nthLastChild = 16, + nthOfType = 17, + nthLastOfType = 18, + mozIsHTML = 19, + unresolved = 20, + mozNativeAnonymous = 21, + mozSystemMetric = 22, + mozLocaleDir = 23, + mozLWTheme = 24, + mozLWThemeBrightText = 25, + mozLWThemeDarkText = 26, + mozWindowInactive = 27, + mozTableBorderNonzero = 28, + mozBrowserFrame = 29, + scope = 30, + negation = 31, + dir = 32, + link = 33, + mozAnyLink = 34, + anyLink = 35, + visited = 36, + active = 37, + checked = 38, + disabled = 39, + enabled = 40, + focus = 41, + focusWithin = 42, + hover = 43, + mozDragOver = 44, + target = 45, + indeterminate = 46, + mozDevtoolsHighlighted = 47, + mozStyleeditorTransitioning = 48, + fullscreen = 49, + mozFullScreen = 50, + mozFocusRing = 51, + mozBroken = 52, + mozLoading = 53, + mozUserDisabled = 54, + mozSuppressed = 55, + mozHandlerClickToPlay = 56, + mozHandlerVulnerableUpdatable = 57, + mozHandlerVulnerableNoUpdate = 58, + mozHandlerDisabled = 59, + mozHandlerBlocked = 60, + mozHandlerCrashed = 61, + mozMathIncrementScriptLevel = 62, + required = 63, + optional = 64, + valid = 65, + invalid = 66, + inRange = 67, + outOfRange = 68, + defaultPseudo = 69, + placeholderShown = 70, + mozReadOnly = 71, + mozReadWrite = 72, + mozSubmitInvalid = 73, + mozUIInvalid = 74, + mozUIValid = 75, + mozMeterOptimum = 76, + mozMeterSubOptimum = 77, + mozMeterSubSubOptimum = 78, + mozPlaceholder = 79, + Count = 80, + NotPseudo = 81, + MAX = 82, + } #[test] fn __bindgen_test_layout_template_3() { assert_eq!(::std::mem::size_of::>() diff --git a/servo/components/style/gecko_bindings/structs_release.rs b/servo/components/style/gecko_bindings/structs_release.rs index 99e028601580..f226110a161c 100644 --- a/servo/components/style/gecko_bindings/structs_release.rs +++ b/servo/components/style/gecko_bindings/structs_release.rs @@ -3186,6 +3186,93 @@ pub mod root { root::mozilla::StyleShapeSource; pub type StyleShapeOutside = root::mozilla::StyleShapeSource; + #[repr(u8)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum CSSPseudoClassType { + empty = 0, + mozOnlyWhitespace = 1, + mozEmptyExceptChildrenWithLocalname = 2, + lang = 3, + mozBoundElement = 4, + root = 5, + any = 6, + firstChild = 7, + firstNode = 8, + lastChild = 9, + lastNode = 10, + onlyChild = 11, + firstOfType = 12, + lastOfType = 13, + onlyOfType = 14, + nthChild = 15, + nthLastChild = 16, + nthOfType = 17, + nthLastOfType = 18, + mozIsHTML = 19, + unresolved = 20, + mozNativeAnonymous = 21, + mozSystemMetric = 22, + mozLocaleDir = 23, + mozLWTheme = 24, + mozLWThemeBrightText = 25, + mozLWThemeDarkText = 26, + mozWindowInactive = 27, + mozTableBorderNonzero = 28, + mozBrowserFrame = 29, + scope = 30, + negation = 31, + dir = 32, + link = 33, + mozAnyLink = 34, + anyLink = 35, + visited = 36, + active = 37, + checked = 38, + disabled = 39, + enabled = 40, + focus = 41, + focusWithin = 42, + hover = 43, + mozDragOver = 44, + target = 45, + indeterminate = 46, + mozDevtoolsHighlighted = 47, + mozStyleeditorTransitioning = 48, + fullscreen = 49, + mozFullScreen = 50, + mozFocusRing = 51, + mozBroken = 52, + mozLoading = 53, + mozUserDisabled = 54, + mozSuppressed = 55, + mozHandlerClickToPlay = 56, + mozHandlerVulnerableUpdatable = 57, + mozHandlerVulnerableNoUpdate = 58, + mozHandlerDisabled = 59, + mozHandlerBlocked = 60, + mozHandlerCrashed = 61, + mozMathIncrementScriptLevel = 62, + required = 63, + optional = 64, + valid = 65, + invalid = 66, + inRange = 67, + outOfRange = 68, + defaultPseudo = 69, + placeholderShown = 70, + mozReadOnly = 71, + mozReadWrite = 72, + mozSubmitInvalid = 73, + mozUIInvalid = 74, + mozUIValid = 75, + mozMeterOptimum = 76, + mozMeterSubOptimum = 77, + mozMeterSubSubOptimum = 78, + mozPlaceholder = 79, + Count = 80, + NotPseudo = 81, + MAX = 82, + } #[test] fn __bindgen_test_layout_template_3() { assert_eq!(::std::mem::size_of::>()