Bug 1867939, part 4: Implemented the ::target-text CSS Pseudo Element. r=emilio,devtools-reviewers,nchevobbe

This patch implements the `::target-text` pseudo element.
Similarly to the Custom Highlight API, this is done implementing
a new Selection type.

Differential Revision: https://phabricator.services.mozilla.com/D195687
This commit is contained in:
Jan-Niklas Jaeschke 2024-04-02 11:43:21 +00:00
parent 16bdc49442
commit b764eaf1f8
13 changed files with 56 additions and 5 deletions

View File

@ -704,6 +704,7 @@ class PageStyleActor extends Actor {
case "::first-line":
case "::selection":
case "::highlight":
case "::target-text":
return true;
case "::marker":
return this._nodeIsListItem(node);

View File

@ -41,11 +41,12 @@ interface nsISelectionController : nsISelectionDisplay
const short SELECTION_FIND = 8;
const short SELECTION_URLSECONDARY = 9;
const short SELECTION_URLSTRIKEOUT = 10;
const short SELECTION_TARGET_TEXT = 11;
// Custom Highlight API
// (see https://drafts.csswg.org/css-highlight-api-1/#enumdef-highlighttype)
const short SELECTION_HIGHLIGHT = 11;
const short SELECTION_HIGHLIGHT = 12;
// End of RawSelectionType values.
const short NUM_SELECTIONTYPES = 12;
const short NUM_SELECTIONTYPES = 13;
// SelectionRegion values:
const short SELECTION_ANCHOR_REGION = 0;
@ -311,6 +312,7 @@ enum class SelectionType : RawSelectionType
eFind = nsISelectionController::SELECTION_FIND,
eURLSecondary = nsISelectionController::SELECTION_URLSECONDARY,
eURLStrikeout = nsISelectionController::SELECTION_URLSTRIKEOUT,
eTargetText = nsISelectionController::SELECTION_TARGET_TEXT,
eHighlight = nsISelectionController::SELECTION_HIGHLIGHT,
};
@ -327,6 +329,7 @@ static const SelectionType kPresentSelectionTypes[] = {
SelectionType::eFind,
SelectionType::eURLSecondary,
SelectionType::eURLStrikeout,
SelectionType::eTargetText,
SelectionType::eHighlight,
};

View File

@ -156,9 +156,10 @@ PeekOffsetStruct::PeekOffsetStruct(nsSelectionAmount aAmount,
} // namespace mozilla
// Array which contains index of each SelecionType in Selection::mDOMSelections.
// For avoiding using if nor switch to retrieve the index, this needs to have
// -1 for SelectionTypes which won't be created its Selection instance.
// Array which contains index of each SelectionType in
// Selection::mDOMSelections. For avoiding using if nor switch to retrieve the
// index, this needs to have -1 for SelectionTypes which won't be created its
// Selection instance.
static const int8_t kIndexOfSelections[] = {
-1, // SelectionType::eInvalid
-1, // SelectionType::eNone
@ -172,6 +173,7 @@ static const int8_t kIndexOfSelections[] = {
7, // SelectionType::eFind
8, // SelectionType::eURLSecondary
9, // SelectionType::eURLStrikeout
10, // SelectionType::eTargetText
-1, // SelectionType::eHighlight
};

View File

@ -2402,6 +2402,15 @@ already_AddRefed<ComputedStyle> nsIFrame::ComputeHighlightSelectionStyle(
*element, PseudoStyleType::highlight, aHighlightName, Style());
}
already_AddRefed<ComputedStyle> nsIFrame::ComputeTargetTextStyle() const {
const Element* element = FindElementAncestorForMozSelection(GetContent());
if (!element) {
return nullptr;
}
return PresContext()->StyleSet()->ProbePseudoElementStyle(
*element, PseudoStyleType::targetText, nullptr, Style());
}
template <typename SizeOrMaxSize>
static inline bool IsIntrinsicKeyword(const SizeOrMaxSize& aSize) {
// All keywords other than auto/none/-moz-available depend on intrinsic sizes.

View File

@ -937,6 +937,8 @@ class nsIFrame : public nsQueryFrame {
already_AddRefed<ComputedStyle> ComputeHighlightSelectionStyle(
nsAtom* aHighlightName);
already_AddRefed<ComputedStyle> ComputeTargetTextStyle() const;
/**
* Accessor functions for geometric parent.
*/

View File

@ -5676,6 +5676,10 @@ bool nsTextFrame::GetSelectionTextColors(SelectionType aSelectionType,
aHighlightName, aBackground);
return hasForeground || hasBackground;
}
case SelectionType::eTargetText: {
aTextPaintStyle.GetTargetTextColors(aForeground, aBackground);
return true;
}
case SelectionType::eURLSecondary:
aTextPaintStyle.GetURLSecondaryColor(aForeground);
*aBackground = NS_RGBA(0, 0, 0, 0);

View File

@ -213,6 +213,24 @@ void nsTextPaintStyle::GetHighlightColors(nscolor* aForeColor,
*aBackColor = NS_TRANSPARENT;
}
void nsTextPaintStyle::GetTargetTextColors(nscolor* aForeColor,
nscolor* aBackColor) {
NS_ASSERTION(aForeColor, "aForeColor is null");
NS_ASSERTION(aBackColor, "aBackColor is null");
const RefPtr<const ComputedStyle> targetTextStyle =
mFrame->ComputeTargetTextStyle();
if (targetTextStyle) {
*aForeColor = targetTextStyle->GetVisitedDependentColor(
&nsStyleText::mWebkitTextFillColor);
*aBackColor = targetTextStyle->GetVisitedDependentColor(
&nsStyleBackground::mBackgroundColor);
return;
}
// XXX(:jjaschke): Before shipping this feature, a sensible set of colors must
// be set (Bug 1867940).
// in the meantime, use the colors of find selection.
GetHighlightColors(aForeColor, aBackColor);
}
bool nsTextPaintStyle::GetCustomHighlightTextColor(nsAtom* aHighlightName,
nscolor* aForeColor) {
NS_ASSERTION(aForeColor, "aForeColor is null");

View File

@ -65,6 +65,7 @@ class MOZ_STACK_CLASS nsTextPaintStyle {
*/
bool GetSelectionColors(nscolor* aForeColor, nscolor* aBackColor);
void GetHighlightColors(nscolor* aForeColor, nscolor* aBackColor);
void GetTargetTextColors(nscolor* aForeColor, nscolor* aBackColor);
// Computes colors for custom highlights.
// Returns false if there are no rules associated with `aHighlightName`.
bool GetCustomHighlightTextColor(nsAtom* aHighlightName, nscolor* aForeColor);

View File

@ -22,6 +22,7 @@
"::highlight",
"::placeholder",
"::selection",
"::target-text",
"::-moz-color-swatch",
"::-moz-focus-inner",
"::-moz-meter-bar",

View File

@ -51,6 +51,7 @@ CSS_PSEUDO_ELEMENT(highlight, ":highlight", 0)
CSS_PSEUDO_ELEMENT(selection, ":selection",
CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS)
CSS_PSEUDO_ELEMENT(targetText, ":target-text", 0)
// XXXbz should we really allow random content to style these? Maybe
// use our flags to prevent that?
CSS_PSEUDO_ELEMENT(mozFocusInner, ":-moz-focus-inner", 0)

View File

@ -130,6 +130,8 @@ class nsCSSPseudoElements {
switch (aType) {
case Type::highlight:
return mozilla::StaticPrefs::dom_customHighlightAPI_enabled();
case Type::targetText:
return mozilla::StaticPrefs::dom_text_fragments_enabled();
case Type::sliderTrack:
case Type::sliderThumb:
case Type::sliderFill:

View File

@ -159,6 +159,11 @@ impl PseudoElement {
matches!(*self, Self::Highlight(_))
}
/// Whether this pseudo-element is the ::target-text pseudo.
#[inline]
pub fn is_target_text(&self) -> bool {
*self == PseudoElement::TargetText
}
/// Whether this pseudo-element supports user action selectors.
pub fn supports_user_action_state(&self) -> bool {
(self.flags() & structs::CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE) != 0
@ -168,6 +173,7 @@ impl PseudoElement {
pub fn enabled_in_content(&self) -> bool {
match *self {
Self::Highlight(..) => pref!("dom.customHighlightAPI.enabled"),
Self::TargetText => pref!("dom.text_fragments.enabled"),
Self::SliderFill | Self::SliderTrack | Self::SliderThumb => {
pref!("layout.css.modern-range-pseudos.enabled")
},

View File

@ -2487,6 +2487,7 @@ STATIC_ATOMS = [
PseudoElementAtom("PseudoElement_firstLine", ":first-line"),
PseudoElementAtom("PseudoElement_highlight", ":highlight"),
PseudoElementAtom("PseudoElement_selection", ":selection"),
PseudoElementAtom("PseudoElement_targetText", ":target-text"),
PseudoElementAtom("PseudoElement_mozFocusInner", ":-moz-focus-inner"),
PseudoElementAtom("PseudoElement_mozNumberSpinBox", ":-moz-number-spin-box"),
PseudoElementAtom("PseudoElement_mozNumberSpinUp", ":-moz-number-spin-up"),