From 7155f2665a9a5b81aa903d87754c84c57a0e2477 Mon Sep 17 00:00:00 2001 From: Razvan Maries Date: Thu, 26 Mar 2020 16:52:18 +0200 Subject: [PATCH] Backed out changeset ac0d06c0ca93 (bug 1624080) for assertion failures. CLOSED TREE --- .../shared/css/generated/properties-db.js | 4 - layout/base/nsPresContext.cpp | 29 +-- layout/base/nsPresContext.h | 5 +- layout/forms/nsMeterFrame.cpp | 6 +- layout/forms/nsNumberControlFrame.cpp | 5 +- layout/forms/nsProgressFrame.cpp | 6 +- layout/forms/nsRangeFrame.cpp | 8 +- .../forms/button/appearance-revert-ref.html | 2 - .../forms/button/appearance-revert.html | 2 - layout/reftests/forms/button/reftest.list | 2 - layout/style/ComputedStyle.h | 13 -- layout/style/ServoBindings.toml | 2 + layout/style/res/forms.css | 2 - servo/components/style/properties/cascade.rs | 34 +-- .../style/properties/computed_value_flags.rs | 14 -- .../style/properties/properties.mako.rs | 114 ++++------ servo/components/style/rule_tree/mod.rs | 194 ++++++++++++++++++ .../components/style/values/specified/box.rs | 14 +- servo/ports/geckolib/glue.rs | 25 +++ widget/nsNativeTheme.cpp | 3 +- 20 files changed, 308 insertions(+), 176 deletions(-) delete mode 100644 layout/reftests/forms/button/appearance-revert-ref.html delete mode 100644 layout/reftests/forms/button/appearance-revert.html diff --git a/devtools/shared/css/generated/properties-db.js b/devtools/shared/css/generated/properties-db.js index 4abecbc0409f..d213ef360712 100644 --- a/devtools/shared/css/generated/properties-db.js +++ b/devtools/shared/css/generated/properties-db.js @@ -264,9 +264,7 @@ exports.CSS_PROPERTIES = { "radio-label", "radiomenuitem", "range", - "range-progress", "range-thumb", - "range-track", "resizer", "resizerpanel", "revert", @@ -1583,9 +1581,7 @@ exports.CSS_PROPERTIES = { "radio-label", "radiomenuitem", "range", - "range-progress", "range-thumb", - "range-track", "resizer", "resizerpanel", "revert", diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 10d7b3a49151..4f0d0137240f 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -1628,23 +1628,28 @@ void nsPresContext::CountReflows(const char* aName, nsIFrame* aFrame) { bool nsPresContext::HasAuthorSpecifiedRules(const nsIFrame* aFrame, uint32_t aRuleTypeMask) const { - MOZ_ASSERT(aFrame->StyleDisplay()->HasAppearance(), - "This should only be used to disable native appearance"); - const bool padding = aRuleTypeMask & NS_AUTHOR_SPECIFIED_PADDING; - const bool borderBackground = - aRuleTypeMask & NS_AUTHOR_SPECIFIED_BORDER_OR_BACKGROUND; - const auto& style = *aFrame->Style(); + Element* elem = aFrame->GetContent()->AsElement(); - if (padding && style.HasAppearanceAndAuthorSpecifiedPadding()) { - return true; + // We need to handle non-generated content pseudos too, so we use + // the parent of generated content pseudo to be consistent. + if (elem->GetPseudoElementType() != PseudoStyleType::NotPseudo) { + MOZ_ASSERT(elem->GetParent(), "Pseudo element has no parent element?"); + elem = elem->GetParent()->AsElement(); + } + if (MOZ_UNLIKELY(!elem->HasServoData())) { + // Probably shouldn't happen, but does. See bug 1387953 + return false; } - if (borderBackground && - style.HasAppearanceAndAuthorSpecifiedBorderOrBackground()) { - return true; + // Anonymous boxes are more complicated, and we just assume that they + // cannot have any author-specified rules here. + if (aFrame->Style()->IsAnonBox()) { + return false; } - return false; + auto* set = PresShell()->StyleSet()->RawSet(); + return Servo_HasAuthorSpecifiedRules(set, aFrame->Style(), elem, + aRuleTypeMask); } gfxUserFontSet* nsPresContext::GetUserFontSet() { diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index b59ca86e5960..4300c078641b 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -117,8 +117,9 @@ enum class nsLayoutPhase : uint8_t { #endif /* Used by nsPresContext::HasAuthorSpecifiedRules */ -#define NS_AUTHOR_SPECIFIED_BORDER_OR_BACKGROUND (1 << 0) -#define NS_AUTHOR_SPECIFIED_PADDING (1 << 1) +#define NS_AUTHOR_SPECIFIED_BACKGROUND (1 << 0) +#define NS_AUTHOR_SPECIFIED_BORDER (1 << 1) +#define NS_AUTHOR_SPECIFIED_PADDING (1 << 2) class nsRootPresContext; diff --git a/layout/forms/nsMeterFrame.cpp b/layout/forms/nsMeterFrame.cpp index b85b3b5608f2..1d30294b0f62 100644 --- a/layout/forms/nsMeterFrame.cpp +++ b/layout/forms/nsMeterFrame.cpp @@ -232,9 +232,11 @@ bool nsMeterFrame::ShouldUseNativeStyle() const { // background. return StyleDisplay()->mAppearance == StyleAppearance::Meter && !PresContext()->HasAuthorSpecifiedRules( - this, NS_AUTHOR_SPECIFIED_BORDER_OR_BACKGROUND) && + this, + NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND) && barFrame && barFrame->StyleDisplay()->mAppearance == StyleAppearance::Meterchunk && !PresContext()->HasAuthorSpecifiedRules( - barFrame, NS_AUTHOR_SPECIFIED_BORDER_OR_BACKGROUND); + barFrame, + NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND); } diff --git a/layout/forms/nsNumberControlFrame.cpp b/layout/forms/nsNumberControlFrame.cpp index fd4330c6cd10..a22eed6ccf64 100644 --- a/layout/forms/nsNumberControlFrame.cpp +++ b/layout/forms/nsNumberControlFrame.cpp @@ -231,8 +231,9 @@ bool nsNumberControlFrame::SpinnerDownButtonIsDepressed() const { ->NumberSpinnerDownButtonIsDepressed(); } -#define STYLES_DISABLING_NATIVE_THEMING \ - NS_AUTHOR_SPECIFIED_BORDER_OR_BACKGROUND | NS_AUTHOR_SPECIFIED_PADDING +#define STYLES_DISABLING_NATIVE_THEMING \ + NS_AUTHOR_SPECIFIED_BACKGROUND | NS_AUTHOR_SPECIFIED_PADDING | \ + NS_AUTHOR_SPECIFIED_BORDER bool nsNumberControlFrame::ShouldUseNativeStyleForSpinner() const { MOZ_ASSERT(mSpinUp && mSpinDown, diff --git a/layout/forms/nsProgressFrame.cpp b/layout/forms/nsProgressFrame.cpp index b3eff1c23da6..4371e45fd3be 100644 --- a/layout/forms/nsProgressFrame.cpp +++ b/layout/forms/nsProgressFrame.cpp @@ -248,10 +248,12 @@ bool nsProgressFrame::ShouldUseNativeStyle() const { // background. return StyleDisplay()->mAppearance == StyleAppearance::ProgressBar && !PresContext()->HasAuthorSpecifiedRules( - this, NS_AUTHOR_SPECIFIED_BORDER_OR_BACKGROUND) && + this, + NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND) && barFrame && barFrame->StyleDisplay()->mAppearance == StyleAppearance::Progresschunk && !PresContext()->HasAuthorSpecifiedRules( - barFrame, NS_AUTHOR_SPECIFIED_BORDER_OR_BACKGROUND); + barFrame, + NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND); } diff --git a/layout/forms/nsRangeFrame.cpp b/layout/forms/nsRangeFrame.cpp index 09bf372ded8a..a4b7ad151db5 100644 --- a/layout/forms/nsRangeFrame.cpp +++ b/layout/forms/nsRangeFrame.cpp @@ -800,15 +800,17 @@ double nsRangeFrame::GetValue() const { .toDouble(); } -#define STYLES_DISABLING_NATIVE_THEMING \ - NS_AUTHOR_SPECIFIED_BORDER_OR_BACKGROUND | NS_AUTHOR_SPECIFIED_PADDING +#define STYLES_DISABLING_NATIVE_THEMING \ + NS_AUTHOR_SPECIFIED_BACKGROUND | NS_AUTHOR_SPECIFIED_PADDING | \ + NS_AUTHOR_SPECIFIED_BORDER bool nsRangeFrame::ShouldUseNativeStyle() const { nsIFrame* trackFrame = mTrackDiv->GetPrimaryFrame(); nsIFrame* progressFrame = mProgressDiv->GetPrimaryFrame(); nsIFrame* thumbFrame = mThumbDiv->GetPrimaryFrame(); - return StyleDisplay()->mAppearance == StyleAppearance::Range && trackFrame && + return (StyleDisplay()->mAppearance == StyleAppearance::Range) && + trackFrame && !PresContext()->HasAuthorSpecifiedRules( trackFrame, STYLES_DISABLING_NATIVE_THEMING) && progressFrame && diff --git a/layout/reftests/forms/button/appearance-revert-ref.html b/layout/reftests/forms/button/appearance-revert-ref.html deleted file mode 100644 index 9e863880dfb4..000000000000 --- a/layout/reftests/forms/button/appearance-revert-ref.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/layout/reftests/forms/button/appearance-revert.html b/layout/reftests/forms/button/appearance-revert.html deleted file mode 100644 index 06f1d045d217..000000000000 --- a/layout/reftests/forms/button/appearance-revert.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/layout/reftests/forms/button/reftest.list b/layout/reftests/forms/button/reftest.list index 3b397f2977ff..14c23e6fd780 100644 --- a/layout/reftests/forms/button/reftest.list +++ b/layout/reftests/forms/button/reftest.list @@ -50,5 +50,3 @@ fails-if(Android&&nativeThemePref) == disabled-1.html disabled-1-ref.html == dynamic-text-indent.html dynamic-text-indent-ref.html == 1349646.html 1349646-ref.html - -== appearance-revert.html appearance-revert-ref.html diff --git a/layout/style/ComputedStyle.h b/layout/style/ComputedStyle.h index 5ae45644daf4..0ac0ba1ec902 100644 --- a/layout/style/ComputedStyle.h +++ b/layout/style/ComputedStyle.h @@ -122,19 +122,6 @@ class ComputedStyle { return mPseudoType != PseudoStyleType::NotPseudo; } - // Whether there are author-specified rules for padding properties. - // Only returns something meaningful if the appearance property is not `none`. - bool HasAppearanceAndAuthorSpecifiedPadding() const { - return bool(Flags() & Flag::HAS_AUTHOR_SPECIFIED_PADDING); - } - - // Whether there are author-specified rules for border or background - // properties. - // Only returns something meaningful if the appearance property is not `none`. - bool HasAppearanceAndAuthorSpecifiedBorderOrBackground() const { - return bool(Flags() & Flag::HAS_AUTHOR_SPECIFIED_BORDER_BACKGROUND); - } - // Does this ComputedStyle or any of its ancestors have text // decoration lines? // Differs from nsStyleTextReset::HasTextDecorationLines, which tests diff --git a/layout/style/ServoBindings.toml b/layout/style/ServoBindings.toml index 7821e6c7cd8d..3d550fe4439c 100644 --- a/layout/style/ServoBindings.toml +++ b/layout/style/ServoBindings.toml @@ -167,6 +167,8 @@ rusty-enums = [ "mozilla::StyleMaskComposite", ] whitelist-vars = [ + "NS_AUTHOR_SPECIFIED_.*", + "NS_THEME_.*", "NS_ATTRVALUE_.*", "NODE_.*", "ELEMENT_.*", diff --git a/layout/style/res/forms.css b/layout/style/res/forms.css index f4a3b1a92c0f..7022c666104b 100644 --- a/layout/style/res/forms.css +++ b/layout/style/res/forms.css @@ -909,7 +909,6 @@ input[type=range]::-moz-focus-outer { * set the width/height of this pseudo-element. */ input[type=range]::-moz-range-track { - -moz-appearance: range-track !important; /* Prevent styling that would change the type of frame we construct. */ display: block !important; float: none !important; @@ -935,7 +934,6 @@ input[type=range][orient=vertical]::-moz-range-track { * is ignored. */ input[type=range]::-moz-range-progress { - -moz-appearance: range-progress !important; /* Prevent styling that would change the type of frame we construct. */ display: block !important; float: none !important; diff --git a/servo/components/style/properties/cascade.rs b/servo/components/style/properties/cascade.rs index 415c8084d856..9d3660730451 100644 --- a/servo/components/style/properties/cascade.rs +++ b/servo/components/style/properties/cascade.rs @@ -13,7 +13,7 @@ use crate::media_queries::Device; use crate::properties::{ComputedValues, StyleBuilder}; use crate::properties::{LonghandId, LonghandIdSet, CSSWideKeyword}; use crate::properties::{PropertyDeclaration, PropertyDeclarationId, DeclarationImportanceIterator}; -use crate::properties::{CASCADE_PROPERTY, ComputedValueFlags}; +use crate::properties::CASCADE_PROPERTY; use crate::rule_cache::{RuleCache, RuleCacheConditions}; use crate::rule_tree::StrongRuleNode; use crate::selector_parser::PseudoElement; @@ -411,7 +411,6 @@ struct Cascade<'a, 'b: 'a> { context: &'a mut computed::Context<'b>, cascade_mode: CascadeMode<'a>, seen: LonghandIdSet, - author_specified: LonghandIdSet, reverted: PerOrigin, } @@ -421,7 +420,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { context, cascade_mode, seen: LonghandIdSet::default(), - author_specified: LonghandIdSet::default(), reverted: Default::default(), } } @@ -559,9 +557,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { } self.seen.insert(physical_longhand_id); - if origin == Origin::Author { - self.author_specified.insert(physical_longhand_id); - } let unset = css_wide_keyword.map_or(false, |css_wide_keyword| { match css_wide_keyword { @@ -684,15 +679,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { if let Some(svg) = builder.get_svg_if_mutated() { svg.fill_arrays(); } - - if !builder.get_box().clone__moz_appearance().is_none() { - if self.author_specified.contains_any(LonghandIdSet::border_background_properties()) { - builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_BORDER_BACKGROUND); - } - if self.author_specified.contains_any(LonghandIdSet::padding_properties()) { - builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_PADDING); - } - } } #[cfg(feature = "servo")] @@ -713,26 +699,12 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { None => return false, }; - let builder = &mut self.context.builder; - - let cached_style = match cache.find(guards, &builder) { + let cached_style = match cache.find(guards, &self.context.builder) { Some(style) => style, None => return false, }; - builder.copy_reset_from(cached_style); - - // We're using the same reset style as another element, and we'll skip - // applying the relevant properties. So we need to do the relevant - // bookkeeping here to keep these two bits correct. - // - // Note that all the properties involved are non-inherited, so we don't - // need to do anything else other than just copying the bits over. - let reset_props_bits = - ComputedValueFlags::HAS_AUTHOR_SPECIFIED_BORDER_BACKGROUND | - ComputedValueFlags::HAS_AUTHOR_SPECIFIED_PADDING; - builder.add_flags(cached_style.flags & reset_props_bits); - + self.context.builder.copy_reset_from(cached_style); true } diff --git a/servo/components/style/properties/computed_value_flags.rs b/servo/components/style/properties/computed_value_flags.rs index 221363ba4b14..b5294093adfe 100644 --- a/servo/components/style/properties/computed_value_flags.rs +++ b/servo/components/style/properties/computed_value_flags.rs @@ -70,20 +70,6 @@ bitflags! { /// Whether this element is inside an `opacity: 0` subtree. const IS_IN_OPACITY_ZERO_SUBTREE = 1 << 12; - - /// Whether there are author-specified rules for border-* properties - /// (except border-image-*), background-color, or background-image. - /// - /// TODO(emilio): Maybe do include border-image, see: - /// - /// https://github.com/w3c/csswg-drafts/issues/4777#issuecomment-604424845 - const HAS_AUTHOR_SPECIFIED_BORDER_BACKGROUND = 1 << 13; - - /// Whether there are author-specified rules for padding-* properties. - /// - /// FIXME(emilio): Try to merge this with BORDER_BACKGROUND, see - /// https://github.com/w3c/csswg-drafts/issues/4777 - const HAS_AUTHOR_SPECIFIED_PADDING = 1 << 14; } } diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs index b739ca63173a..c39dc6f23da1 100644 --- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -750,52 +750,6 @@ static ${name}: LonghandIdSet = LonghandIdSet { }; -<% - logical_groups = defaultdict(list) - for prop in data.longhands: - if prop.logical_group: - logical_groups[prop.logical_group].append(prop) - - for group, props in logical_groups.iteritems(): - logical_count = sum(1 for p in props if p.logical) - if logical_count * 2 != len(props): - raise RuntimeError("Logical group {} has ".format(group) + - "unbalanced logical / physical properties") - - FIRST_LINE_RESTRICTIONS = PropertyRestrictions.first_line(data) - FIRST_LETTER_RESTRICTIONS = PropertyRestrictions.first_letter(data) - MARKER_RESTRICTIONS = PropertyRestrictions.marker(data) - PLACEHOLDER_RESTRICTIONS = PropertyRestrictions.placeholder(data) - CUE_RESTRICTIONS = PropertyRestrictions.cue(data) - - def restriction_flags(property): - name = property.name - flags = [] - if name in FIRST_LINE_RESTRICTIONS: - flags.append("APPLIES_TO_FIRST_LINE") - if name in FIRST_LETTER_RESTRICTIONS: - flags.append("APPLIES_TO_FIRST_LETTER") - if name in PLACEHOLDER_RESTRICTIONS: - flags.append("APPLIES_TO_PLACEHOLDER") - if name in MARKER_RESTRICTIONS: - flags.append("APPLIES_TO_MARKER") - if name in CUE_RESTRICTIONS: - flags.append("APPLIES_TO_CUE") - return flags - -%> - -/// A group for properties which may override each other -/// via logical resolution. -#[derive(Clone, Copy, Eq, Hash, PartialEq)] -pub enum LogicalGroup { - % for group in logical_groups.iterkeys(): - /// ${group} - ${to_camel_case(group)}, - % endfor -} - - /// A set of longhand properties #[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq)] pub struct LonghandIdSet { @@ -883,29 +837,6 @@ impl LonghandIdSet { &HAS_NO_EFFECT_ON_SCROLLBARS } - /// Returns the set of padding properties for the purpose of disabling - /// native appearance. - #[inline] - pub fn padding_properties() -> &'static Self { - <% assert "padding" in logical_groups %> - ${static_longhand_id_set( - "PADDING_PROPERTIES", - lambda p: p.logical_group == "padding" - )} - &PADDING_PROPERTIES - } - - /// Returns the set of border properties for the purpose of disabling native - /// appearance. - #[inline] - pub fn border_background_properties() -> &'static Self { - ${static_longhand_id_set( - "BORDER_BACKGROUND_PROPERTIES", - lambda p: (p.logical_group and p.logical_group.startswith("border")) or p.name in ["background-color", "background-image"] - )} - &BORDER_BACKGROUND_PROPERTIES - } - /// Iterate over the current longhand id set. pub fn iter(&self) -> LonghandIdSetIterator { LonghandIdSetIterator { longhands: self, cur: 0, } @@ -1067,6 +998,51 @@ bitflags! { } } +<% + logical_groups = defaultdict(list) + for prop in data.longhands: + if prop.logical_group: + logical_groups[prop.logical_group].append(prop) + + for group, props in logical_groups.iteritems(): + logical_count = sum(1 for p in props if p.logical) + if logical_count * 2 != len(props): + raise RuntimeError("Logical group {} has ".format(group) + + "unbalanced logical / physical properties") + + FIRST_LINE_RESTRICTIONS = PropertyRestrictions.first_line(data) + FIRST_LETTER_RESTRICTIONS = PropertyRestrictions.first_letter(data) + MARKER_RESTRICTIONS = PropertyRestrictions.marker(data) + PLACEHOLDER_RESTRICTIONS = PropertyRestrictions.placeholder(data) + CUE_RESTRICTIONS = PropertyRestrictions.cue(data) + + def restriction_flags(property): + name = property.name + flags = [] + if name in FIRST_LINE_RESTRICTIONS: + flags.append("APPLIES_TO_FIRST_LINE") + if name in FIRST_LETTER_RESTRICTIONS: + flags.append("APPLIES_TO_FIRST_LETTER") + if name in PLACEHOLDER_RESTRICTIONS: + flags.append("APPLIES_TO_PLACEHOLDER") + if name in MARKER_RESTRICTIONS: + flags.append("APPLIES_TO_MARKER") + if name in CUE_RESTRICTIONS: + flags.append("APPLIES_TO_CUE") + return flags + +%> + +/// A group for properties which may override each other +/// via logical resolution. +#[derive(Clone, Copy, Eq, Hash, PartialEq)] +pub enum LogicalGroup { + % for group in logical_groups.iterkeys(): + /// ${group} + ${to_camel_case(group)}, + % endfor +} + /// An identifier for a given longhand property. #[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] #[repr(u16)] diff --git a/servo/components/style/rule_tree/mod.rs b/servo/components/style/rule_tree/mod.rs index 484cdee51834..ddac85a80750 100644 --- a/servo/components/style/rule_tree/mod.rs +++ b/servo/components/style/rule_tree/mod.rs @@ -7,6 +7,8 @@ //! The rule tree. use crate::applicable_declarations::ApplicableDeclarationList; +#[cfg(feature = "gecko")] +use crate::gecko::selector_parser::PseudoElement; use crate::hash::{self, FxHashMap}; use crate::properties::{Importance, LonghandIdSet, PropertyDeclarationBlock}; use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards}; @@ -1416,6 +1418,198 @@ impl StrongRuleNode { } } + /// Returns true if any properties specified by `rule_type_mask` was set by + /// an author rule. + #[cfg(feature = "gecko")] + pub fn has_author_specified_rules( + &self, + mut element: E, + mut pseudo: Option, + guards: &StylesheetGuards, + rule_type_mask: u32, + author_colors_allowed: bool, + ) -> bool + where + E: crate::dom::TElement, + { + use crate::gecko_bindings::structs::NS_AUTHOR_SPECIFIED_BACKGROUND; + use crate::gecko_bindings::structs::NS_AUTHOR_SPECIFIED_BORDER; + use crate::gecko_bindings::structs::NS_AUTHOR_SPECIFIED_PADDING; + use crate::properties::{CSSWideKeyword, LonghandId}; + use crate::properties::{PropertyDeclaration, PropertyDeclarationId}; + use std::borrow::Cow; + + // Reset properties: + const BACKGROUND_PROPS: &'static [LonghandId] = + &[LonghandId::BackgroundColor, LonghandId::BackgroundImage]; + + const BORDER_PROPS: &'static [LonghandId] = &[ + LonghandId::BorderTopColor, + LonghandId::BorderTopStyle, + LonghandId::BorderTopWidth, + LonghandId::BorderRightColor, + LonghandId::BorderRightStyle, + LonghandId::BorderRightWidth, + LonghandId::BorderBottomColor, + LonghandId::BorderBottomStyle, + LonghandId::BorderBottomWidth, + LonghandId::BorderLeftColor, + LonghandId::BorderLeftStyle, + LonghandId::BorderLeftWidth, + LonghandId::BorderTopLeftRadius, + LonghandId::BorderTopRightRadius, + LonghandId::BorderBottomRightRadius, + LonghandId::BorderBottomLeftRadius, + LonghandId::BorderInlineStartColor, + LonghandId::BorderInlineStartStyle, + LonghandId::BorderInlineStartWidth, + LonghandId::BorderInlineEndColor, + LonghandId::BorderInlineEndStyle, + LonghandId::BorderInlineEndWidth, + LonghandId::BorderBlockStartColor, + LonghandId::BorderBlockStartStyle, + LonghandId::BorderBlockStartWidth, + LonghandId::BorderBlockEndColor, + LonghandId::BorderBlockEndStyle, + LonghandId::BorderBlockEndWidth, + ]; + + const PADDING_PROPS: &'static [LonghandId] = &[ + LonghandId::PaddingTop, + LonghandId::PaddingRight, + LonghandId::PaddingBottom, + LonghandId::PaddingLeft, + LonghandId::PaddingInlineStart, + LonghandId::PaddingInlineEnd, + LonghandId::PaddingBlockStart, + LonghandId::PaddingBlockEnd, + ]; + + // Set of properties that we are currently interested in. + let mut properties = LonghandIdSet::new(); + + if rule_type_mask & NS_AUTHOR_SPECIFIED_BACKGROUND != 0 { + for id in BACKGROUND_PROPS { + properties.insert(*id); + } + } + if rule_type_mask & NS_AUTHOR_SPECIFIED_BORDER != 0 { + for id in BORDER_PROPS { + properties.insert(*id); + } + } + if rule_type_mask & NS_AUTHOR_SPECIFIED_PADDING != 0 { + for id in PADDING_PROPS { + properties.insert(*id); + } + } + + // If author colors are not allowed, don't look at those properties + // (except for background-color which is special and we handle below). + if !author_colors_allowed { + properties.remove_all(LonghandIdSet::ignored_when_colors_disabled()); + if rule_type_mask & NS_AUTHOR_SPECIFIED_BACKGROUND != 0 { + properties.insert(LonghandId::BackgroundColor); + } + } + + let mut element_rule_node = Cow::Borrowed(self); + + loop { + // We need to be careful not to count styles covered up by + // user-important or UA-important declarations. But we do want to + // catch explicit inherit styling in those and check our parent + // element to see whether we have user styling for those properties. + // Note that we don't care here about inheritance due to lack of a + // specified value, since all the properties we care about are reset + // properties. + + let mut inherited_properties = LonghandIdSet::new(); + let mut have_explicit_ua_inherit = false; + + for node in element_rule_node.self_and_ancestors() { + let source = node.style_source(); + let declarations = if source.is_some() { + source + .as_ref() + .unwrap() + .read(node.cascade_level().guard(guards)) + .declaration_importance_iter() + } else { + continue; + }; + + // Iterate over declarations of the longhands we care about. + let node_importance = node.importance(); + let longhands = declarations.rev().filter_map(|(declaration, importance)| { + if importance != node_importance { + return None; + } + match declaration.id() { + PropertyDeclarationId::Longhand(id) => Some((id, declaration)), + _ => None, + } + }); + + let is_author = node.cascade_level().origin() == Origin::Author; + for (id, declaration) in longhands { + if !properties.contains(id) { + continue; + } + + if is_author { + if !author_colors_allowed { + if let PropertyDeclaration::BackgroundColor(ref color) = *declaration { + if color.is_transparent() { + return true; + } + continue; + } + } + return true; + } + + // This property was set by a non-author rule. + // Stop looking for it in this element's rule + // nodes. + properties.remove(id); + + // However, if it is inherited, then it might be + // inherited from an author rule from an + // ancestor element's rule nodes. + if declaration.get_css_wide_keyword() == Some(CSSWideKeyword::Inherit) { + have_explicit_ua_inherit = true; + inherited_properties.insert(id); + } + } + } + + if !have_explicit_ua_inherit { + break; + } + + // Continue to the parent element and search for the inherited properties. + if let Some(pseudo) = pseudo.take() { + if pseudo.inherits_from_default_values() { + break; + } + } else { + element = match element.inheritance_parent() { + Some(parent) => parent, + None => break, + }; + + let parent_data = element.mutate_data().unwrap(); + let parent_rule_node = parent_data.styles.primary().rules().clone(); + element_rule_node = Cow::Owned(parent_rule_node); + } + + properties = inherited_properties; + } + + false + } + /// Returns true if there is either animation or transition level rule. pub fn has_animation_or_transition_rules(&self) -> bool { self.self_and_ancestors() diff --git a/servo/components/style/values/specified/box.rs b/servo/components/style/values/specified/box.rs index f546e1a3d92a..75da811f08d4 100644 --- a/servo/components/style/values/specified/box.rs +++ b/servo/components/style/values/specified/box.rs @@ -1630,11 +1630,7 @@ pub enum Appearance { RadioLabel, /// nsRangeFrame and its subparts Range, - RangeThumb, // FIXME: This should not be exposed to content. - #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] - RangeProgress, - #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] - RangeTrack, + RangeThumb, /// The resizer background area in a status bar for the resizer widget in /// the corner of a window. #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] @@ -1860,14 +1856,6 @@ pub enum Appearance { Count, } -impl Appearance { - /// Returns whether we're the `none` value. - #[inline] - pub fn is_none(self) -> bool { - self == Appearance::None - } -} - /// A kind of break between two boxes. /// /// https://drafts.csswg.org/css-break/#break-between diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index ad137b061ad0..4eccf5f3c99c 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -3723,6 +3723,31 @@ pub extern "C" fn Servo_SetExplicitStyle(element: &RawGeckoElement, style: &Comp data.styles.primary = Some(unsafe { ArcBorrow::from_ref(style) }.clone_arc()); } +#[no_mangle] +pub extern "C" fn Servo_HasAuthorSpecifiedRules( + raw_data: &RawServoStyleSet, + style: &ComputedValues, + element: &RawGeckoElement, + rule_type_mask: u32, +) -> bool { + let data = PerDocumentStyleData::from_ffi(raw_data).borrow(); + let element = GeckoElement(element); + + let guard = (*GLOBAL_STYLE_DATA).shared_lock.read(); + let guards = StylesheetGuards::same(&guard); + + let pseudo = style.pseudo(); + let author_colors_allowed = data.stylist.device().use_document_colors(); + + style.rules().has_author_specified_rules( + element, + pseudo, + &guards, + rule_type_mask, + author_colors_allowed, + ) +} + fn get_pseudo_style( guard: &SharedRwLockReadGuard, element: GeckoElement, diff --git a/widget/nsNativeTheme.cpp b/widget/nsNativeTheme.cpp index b0a6a83992be..8a9afd876b06 100644 --- a/widget/nsNativeTheme.cpp +++ b/widget/nsNativeTheme.cpp @@ -292,7 +292,8 @@ bool nsNativeTheme::IsWidgetStyled(nsPresContext* aPresContext, aAppearance == StyleAppearance::MenulistButton) && aFrame->GetContent()->IsHTMLElement() && aPresContext->HasAuthorSpecifiedRules( - aFrame, NS_AUTHOR_SPECIFIED_BORDER_OR_BACKGROUND); + aFrame, + NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND); } bool nsNativeTheme::IsDisabled(nsIFrame* aFrame, EventStates aEventStates) {