/* virtual */ void
nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
{
  nsRuleWalker *ruleWalker = aData->mRuleWalker;
  if (aData->mElement->IsHTML() && !ruleWalker->AuthorStyleDisabled()) {
    nsIAtom* tag = aData->mElement->Tag();

    // if we have anchor colors, check if this is an anchor with an href
    if (tag == nsGkAtoms::a) {
      if (mLinkRule || mVisitedRule || mActiveRule) {
        EventStates state =
          nsCSSRuleProcessor::GetContentStateForVisitedHandling(
                                  aData->mElement,
                                  aData->mTreeMatchContext,
                                  aData->mTreeMatchContext.VisitedHandling(),
                                  // If the node being matched is a link,
                                  // it's the relevant link.
                                  nsCSSRuleProcessor::IsLink(aData->mElement));
        if (mLinkRule && state.HasState(NS_EVENT_STATE_UNVISITED)) {
          ruleWalker->Forward(mLinkRule);
          aData->mTreeMatchContext.SetHaveRelevantLink();
        }
        else if (mVisitedRule && state.HasState(NS_EVENT_STATE_VISITED)) {
          ruleWalker->Forward(mVisitedRule);
          aData->mTreeMatchContext.SetHaveRelevantLink();
        }

        // No need to add to the active rule if it's not a link
        if (mActiveRule && nsCSSRuleProcessor::IsLink(aData->mElement) &&
            state.HasState(NS_EVENT_STATE_ACTIVE)) {
          ruleWalker->Forward(mActiveRule);
        }
      } // end link/visited/active rules
    } // end A tag
    // add the rule to handle text-align for a <th>
    else if (tag == nsGkAtoms::th) {
      ruleWalker->Forward(mTableTHRule);
    }
    else if (tag == nsGkAtoms::table) {
      if (aData->mTreeMatchContext.mCompatMode == eCompatibility_NavQuirks) {
        ruleWalker->Forward(mTableQuirkColorRule);
      }
    }
  } // end html element

  // just get the style rules from the content.  For SVG we do this even if
  // author style is disabled, because SVG presentational hints aren't
  // considered style.
  if (!ruleWalker->AuthorStyleDisabled() || aData->mElement->IsSVG()) {
    aData->mElement->WalkContentStyleRules(ruleWalker);
  }

  // http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#language
  // says that the xml:lang attribute overrides HTML's lang attribute,
  // so we need to do this after WalkContentStyleRules.
  nsString lang;
  if (aData->mElement->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang, lang)) {
    ruleWalker->Forward(LangRuleFor(lang));
  }
}
Exemple #2
0
void
nsRangeFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists)
{
  if (IsThemed()) {
    DisplayBorderBackgroundOutline(aBuilder, aLists);
    // Only create items for the thumb. Specifically, we do not want
    // the track to paint, since *our* background is used to paint
    // the track, and we don't want the unthemed track painting over
    // the top of the themed track.
    // This logic is copied from
    // nsContainerFrame::BuildDisplayListForNonBlockChildren as
    // called by BuildDisplayListForInline.
    nsIFrame* thumb = mThumbDiv->GetPrimaryFrame();
    if (thumb) {
      nsDisplayListSet set(aLists, aLists.Content());
      BuildDisplayListForChild(aBuilder, thumb, aDirtyRect, set, DISPLAY_CHILD_INLINE);
    }
  } else {
    BuildDisplayListForInline(aBuilder, aDirtyRect, aLists);
  }

  // Draw a focus outline if appropriate:

  if (!aBuilder->IsForPainting() ||
      !IsVisibleForPainting(aBuilder)) {
    // we don't want the focus ring item for hit-testing or if the item isn't
    // in the area being [re]painted
    return;
  }

  EventStates eventStates = mContent->AsElement()->State();
  if (eventStates.HasState(NS_EVENT_STATE_DISABLED) ||
      !eventStates.HasState(NS_EVENT_STATE_FOCUSRING)) {
    return; // can't have focus or doesn't match :-moz-focusring
  }

  if (!mOuterFocusStyle ||
      !mOuterFocusStyle->StyleBorder()->HasBorder()) {
    // no ::-moz-focus-outer specified border (how style specifies a focus ring
    // for range)
    return;
  }

  const nsStyleDisplay *disp = StyleDisplay();
  if (IsThemed(disp) &&
      PresContext()->GetTheme()->ThemeDrawsFocusForWidget(disp->mAppearance)) {
    return; // the native theme displays its own visual indication of focus
  }

  aLists.Content()->AppendNewToTop(
    new (aBuilder) nsDisplayRangeFocusRing(aBuilder, this));
}
uint64_t
HTMLLinkAccessible::NativeLinkState() const
{
  EventStates eventState = mContent->AsElement()->State();
  if (eventState.HasState(NS_EVENT_STATE_UNVISITED))
    return states::LINKED;

  if (eventState.HasState(NS_EVENT_STATE_VISITED))
    return states::LINKED | states::TRAVERSED;

  // This is a either named anchor (a link with also a name attribute) or
  // it doesn't have any attributes. Check if 'click' event handler is
  // registered, otherwise bail out.
  return nsCoreUtils::HasClickListener(mContent) ? states::LINKED : 0;
}
void
nsNumberControlFrame::ContentStatesChanged(EventStates aStates)
{
  if (aStates.HasState(NS_EVENT_STATE_DISABLED)) {
    nsContentUtils::AddScriptRunner(new SyncDisabledStateEvent(this));
  }
}
uint64_t HTMLButtonAccessible::NativeState() const {
  uint64_t state = HyperTextAccessibleWrap::NativeState();

  EventStates elmState = mContent->AsElement()->State();
  if (elmState.HasState(NS_EVENT_STATE_DEFAULT)) state |= states::DEFAULT;

  return state;
}
void
nsNumberControlFrame::SyncDisabledState()
{
  EventStates eventStates = mContent->AsElement()->State();
  if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
    mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, EmptyString(),
                        true);
  } else {
    mTextField->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, true);
  }
}
EventStates
HTMLTextAreaElement::IntrinsicState() const
{
  EventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();

  if (HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
    state |= NS_EVENT_STATE_REQUIRED;
  } else {
    state |= NS_EVENT_STATE_OPTIONAL;
  }

  if (IsCandidateForConstraintValidation()) {
    if (IsValid()) {
      state |= NS_EVENT_STATE_VALID;
    } else {
      state |= NS_EVENT_STATE_INVALID;
      // :-moz-ui-invalid always apply if the element suffers from a custom
      // error and never applies if novalidate is set on the form owner.
      if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
          (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
           (mCanShowInvalidUI && ShouldShowValidityUI()))) {
        state |= NS_EVENT_STATE_MOZ_UI_INVALID;
      }
    }

    // :-moz-ui-valid applies if all the following are true:
    // 1. The element is not focused, or had either :-moz-ui-valid or
    //    :-moz-ui-invalid applying before it was focused ;
    // 2. The element is either valid or isn't allowed to have
    //    :-moz-ui-invalid applying ;
    // 3. The element has no form owner or its form owner doesn't have the
    //    novalidate attribute set ;
    // 4. The element has already been modified or the user tried to submit the
    //    form owner while invalid.
    if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
        (mCanShowValidUI && ShouldShowValidityUI() &&
         (IsValid() || (state.HasState(NS_EVENT_STATE_MOZ_UI_INVALID) &&
                        !mCanShowInvalidUI)))) {
      state |= NS_EVENT_STATE_MOZ_UI_VALID;
    }
  }

  if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
      IsValueEmpty()) {
    state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
  }

  return state;
}
// progressbar:
bool
nsNativeTheme::IsIndeterminateProgress(nsIFrame* aFrame,
                                       EventStates aEventStates)
{
  if (!aFrame || !aFrame->GetContent())
    return false;

  if (aFrame->GetContent()->IsHTML(nsGkAtoms::progress)) {
    return aEventStates.HasState(NS_EVENT_STATE_INDETERMINATE);
  }

  return aFrame->GetContent()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mode,
                                           NS_LITERAL_STRING("undetermined"),
                                           eCaseMatters);
}
bool
nsNativeTheme::IsDisabled(nsIFrame* aFrame, EventStates aEventStates)
{
  if (!aFrame) {
    return false;
  }

  nsIContent* content = aFrame->GetContent();
  if (!content) {
    return false;
  }

  if (content->IsHTML()) {
    return aEventStates.HasState(NS_EVENT_STATE_DISABLED);
  }

  // For XML/XUL elements, an attribute must be equal to the literal
  // string "true" to be counted as true.  An empty string should _not_
  // be counted as true.
  return content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
                              NS_LITERAL_STRING("true"), eCaseMatters);
}
/**
 * Calculates the change hint and the restyle hint for a given content state
 * change.
 *
 * This is called from both Restyle managers.
 */
void
RestyleManagerBase::ContentStateChangedInternal(Element* aElement,
                                                EventStates aStateMask,
                                                nsChangeHint* aOutChangeHint,
                                                nsRestyleHint* aOutRestyleHint)
{
  MOZ_ASSERT(aOutChangeHint);
  MOZ_ASSERT(aOutRestyleHint);

  StyleSetHandle styleSet = PresContext()->StyleSet();
  NS_ASSERTION(styleSet, "couldn't get style set");

  *aOutChangeHint = nsChangeHint(0);
  // Any change to a content state that affects which frames we construct
  // must lead to a frame reconstruct here if we already have a frame.
  // Note that we never decide through non-CSS means to not create frames
  // based on content states, so if we already don't have a frame we don't
  // need to force a reframe -- if it's needed, the HasStateDependentStyle
  // call will handle things.
  nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
  CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
  if (primaryFrame) {
    // If it's generated content, ignore LOADING/etc state changes on it.
    if (!primaryFrame->IsGeneratedContentFrame() &&
        aStateMask.HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
                                         NS_EVENT_STATE_USERDISABLED |
                                         NS_EVENT_STATE_SUPPRESSED |
                                         NS_EVENT_STATE_LOADING)) {
      *aOutChangeHint = nsChangeHint_ReconstructFrame;
    } else {
      uint8_t app = primaryFrame->StyleDisplay()->mAppearance;
      if (app) {
        nsITheme* theme = PresContext()->GetTheme();
        if (theme &&
            theme->ThemeSupportsWidget(PresContext(), primaryFrame, app)) {
          bool repaint = false;
          theme->WidgetStateChanged(primaryFrame, app, nullptr, &repaint,
                                    nullptr);
          if (repaint) {
            *aOutChangeHint |= nsChangeHint_RepaintFrame;
          }
        }
      }
    }

    pseudoType = primaryFrame->StyleContext()->GetPseudoType();

    primaryFrame->ContentStatesChanged(aStateMask);
  }

  if (pseudoType >= CSSPseudoElementType::Count) {
    *aOutRestyleHint = styleSet->HasStateDependentStyle(aElement, aStateMask);
  } else if (nsCSSPseudoElements::PseudoElementSupportsUserActionState(
               pseudoType)) {
    // If aElement is a pseudo-element, we want to check to see whether there
    // are any state-dependent rules applying to that pseudo.
    Element* ancestor =
      ElementForStyleContext(nullptr, primaryFrame, pseudoType);
    *aOutRestyleHint = styleSet->HasStateDependentStyle(ancestor, pseudoType,
                                                        aElement, aStateMask);
  } else {
    *aOutRestyleHint = nsRestyleHint(0);
  }

  if (aStateMask.HasState(NS_EVENT_STATE_HOVER) && *aOutRestyleHint != 0) {
    IncrementHoverGeneration();
  }

  if (aStateMask.HasState(NS_EVENT_STATE_VISITED)) {
    // Exposing information to the page about whether the link is
    // visited or not isn't really something we can worry about here.
    // FIXME: We could probably do this a bit better.
    *aOutChangeHint |= nsChangeHint_RepaintFrame;
  }
}