forked from mirrors/gecko-dev
Bug 1868316 - Prototype a user-find css property to control findability of text. r=jfkthame
Nightly-only for now waiting on CSSWG discussion. Differential Revision: https://phabricator.services.mozilla.com/D199727
This commit is contained in:
parent
3bc607893d
commit
b59c93386c
16 changed files with 208 additions and 8 deletions
|
|
@ -192,6 +192,12 @@ let runTests = t.step_func_done(function() {
|
|||
`, "ZWSP should be ignored");
|
||||
|
||||
testFindable(2, " ", "a b c", "Collapsed whitespace");
|
||||
|
||||
// TODO(emilio): This might be worth discussing in the spec. For now
|
||||
// hard-coding our implementation.
|
||||
testFindable(false, "find me", `
|
||||
Do you find <span style="user-find: none">not findable</span> me?
|
||||
`, "boundary-crossing user-find: none");
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ use.counter.error:
|
|||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 2309 use counter metrics (excludes denominators).
|
||||
# Total of 2311 use counter metrics (excludes denominators).
|
||||
# Total of 358 'page' use counters.
|
||||
use.counter.page:
|
||||
svgsvgelement_getelementbyid:
|
||||
|
|
@ -15735,7 +15735,7 @@ use.counter.deprecated_ops.doc:
|
|||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 696 'CSS (page)' use counters.
|
||||
# Total of 697 'CSS (page)' use counters.
|
||||
use.counter.css.page:
|
||||
css_align_content:
|
||||
type: counter
|
||||
|
|
@ -17794,6 +17794,23 @@ use.counter.css.page:
|
|||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_user_find:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a page used the CSS property user-find.
|
||||
Compare against `use.counter.top_level_content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_user_select:
|
||||
type: counter
|
||||
description: >
|
||||
|
|
@ -27569,7 +27586,7 @@ use.counter.css.page:
|
|||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 696 'CSS (document)' use counters.
|
||||
# Total of 697 'CSS (document)' use counters.
|
||||
use.counter.css.doc:
|
||||
css_align_content:
|
||||
type: counter
|
||||
|
|
@ -29628,6 +29645,23 @@ use.counter.css.doc:
|
|||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_user_find:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a document used the CSS property user-find.
|
||||
Compare against `use.counter.content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_user_select:
|
||||
type: counter
|
||||
description: >
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ rusty-enums = [
|
|||
"mozilla::StyleInert",
|
||||
"mozilla::StyleUserModify",
|
||||
"mozilla::StyleUserInput",
|
||||
"mozilla::StyleUserFind",
|
||||
"mozilla::StyleBoxDirection",
|
||||
"mozilla::StyleRubyAlign",
|
||||
"mozilla::StyleTextSecurity",
|
||||
|
|
|
|||
|
|
@ -153,6 +153,12 @@ enum class StyleUserInput : uint8_t {
|
|||
Auto,
|
||||
};
|
||||
|
||||
// user-find
|
||||
enum class StyleUserFind : uint8_t {
|
||||
Auto,
|
||||
None,
|
||||
};
|
||||
|
||||
// user-modify
|
||||
enum class StyleUserModify : uint8_t {
|
||||
ReadOnly,
|
||||
|
|
|
|||
|
|
@ -2969,6 +2969,7 @@ nsStyleUI::nsStyleUI()
|
|||
: mInert(StyleInert::None),
|
||||
mMozTheme(StyleMozTheme::Auto),
|
||||
mUserInput(StyleUserInput::Auto),
|
||||
mUserFind(StyleUserFind::Auto),
|
||||
mUserModify(StyleUserModify::ReadOnly),
|
||||
mUserFocus(StyleUserFocus::Normal),
|
||||
mPointerEvents(StylePointerEvents::Auto),
|
||||
|
|
@ -2984,6 +2985,7 @@ nsStyleUI::nsStyleUI(const nsStyleUI& aSource)
|
|||
: mInert(aSource.mInert),
|
||||
mMozTheme(aSource.mMozTheme),
|
||||
mUserInput(aSource.mUserInput),
|
||||
mUserFind(aSource.mUserFind),
|
||||
mUserModify(aSource.mUserModify),
|
||||
mUserFocus(aSource.mUserFocus),
|
||||
mPointerEvents(aSource.mPointerEvents),
|
||||
|
|
@ -3041,7 +3043,8 @@ nsChangeHint nsStyleUI::CalcDifference(const nsStyleUI& aNewData) const {
|
|||
hint |= NS_STYLE_HINT_VISUAL | kPointerEventsHint;
|
||||
}
|
||||
|
||||
if (mUserFocus != aNewData.mUserFocus || mUserInput != aNewData.mUserInput) {
|
||||
if (mUserFocus != aNewData.mUserFocus || mUserInput != aNewData.mUserInput ||
|
||||
mUserFind != aNewData.mUserFind) {
|
||||
hint |= nsChangeHint_NeutralChange;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1734,6 +1734,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUI {
|
|||
|
||||
private:
|
||||
mozilla::StyleUserInput mUserInput;
|
||||
mozilla::StyleUserFind mUserFind;
|
||||
mozilla::StyleUserModify mUserModify;
|
||||
mozilla::StyleUserFocus mUserFocus;
|
||||
mozilla::StylePointerEvents mPointerEvents;
|
||||
|
|
@ -1746,6 +1747,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUI {
|
|||
return IsInert() ? mozilla::StyleUserInput::None : mUserInput;
|
||||
}
|
||||
|
||||
mozilla::StyleUserFind UserFind() const { return mUserFind; }
|
||||
|
||||
mozilla::StyleUserModify UserModify() const {
|
||||
return IsInert() ? mozilla::StyleUserModify::ReadOnly : mUserModify;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ prefs = [
|
|||
"layout.css.basic-shape-rect.enabled=true",
|
||||
"layout.css.basic-shape-xywh.enabled=true",
|
||||
"layout.css.transform-box-content-stroke.enabled=true",
|
||||
"layout.css.user-find.enabled=true",
|
||||
]
|
||||
support-files = [
|
||||
"animation_utils.js",
|
||||
|
|
|
|||
|
|
@ -3928,6 +3928,14 @@ var gCSSProperties = {
|
|||
alias_for: "user-select",
|
||||
subproperties: ["user-select"],
|
||||
},
|
||||
"user-find": {
|
||||
domProp: "userFind",
|
||||
inherited: true,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: ["auto"],
|
||||
other_values: ["none"],
|
||||
invalid_values: [],
|
||||
},
|
||||
"user-select": {
|
||||
domProp: "userSelect",
|
||||
inherited: false,
|
||||
|
|
|
|||
|
|
@ -8793,6 +8793,13 @@
|
|||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Whether user-find CSS property is enabled.
|
||||
- name: layout.css.user-find.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Should the :visited selector ever match (otherwise :link matches instead)?
|
||||
- name: layout.css.visited_links_enabled
|
||||
type: bool
|
||||
|
|
|
|||
|
|
@ -78,6 +78,19 @@ ${helpers.single_keyword(
|
|||
affects="",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
"user-find",
|
||||
"auto none",
|
||||
engines="gecko",
|
||||
gecko_ffi_name="mUserFind",
|
||||
gecko_enum_prefix="StyleUserFind",
|
||||
animation_value_type="discrete",
|
||||
gecko_pref="layout.css.user-find.enabled",
|
||||
spec="Prototype of solution proposed in https://github.com/w3c/csswg-drafts/issues/3460",
|
||||
has_effect_on_gecko_scrollbars=False,
|
||||
affects="",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
"caret-color",
|
||||
"color::CaretColor",
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ assert_not_inherited('appearance', 'none', 'auto');
|
|||
assert_inherited('caret-color', currentColor, 'rgba(42, 53, 64, 0.75)');
|
||||
assert_inherited('caret-shape', 'auto', 'bar');
|
||||
assert_inherited('cursor', 'auto', 'pointer');
|
||||
if (CSS.supports('user-find', 'auto')) {
|
||||
assert_inherited('user-find', 'auto', 'none');
|
||||
}
|
||||
assert_not_inherited('nav-down', 'auto', '#foo');
|
||||
assert_not_inherited('nav-left', 'auto', '#foo');
|
||||
assert_not_inherited('nav-right', 'auto', '#foo');
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS UI Level 4: getComputedStyle().userFind</title>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/3460">
|
||||
<meta name="assert" content="user-find computed value is as specified.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
test_computed_value("user-find", "auto");
|
||||
test_computed_value("user-find", "none");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS UI Level 4: parsing user-find with invalid values</title>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/3460">
|
||||
<meta name="assert" content="user-find supports only the grammar 'auto | none'.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_invalid_value("user-find", "visible");
|
||||
test_invalid_value("user-find", "never");
|
||||
test_invalid_value("user-find", "10px");
|
||||
test_invalid_value("user-find", "'none'");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS UI Level 4: parsing user-find with valid values</title>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/3460">
|
||||
<meta name="assert" content="user-find supports the grammar 'auto | none'.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_valid_value("user-find", "auto");
|
||||
test_valid_value("user-find", "none");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/3460">
|
||||
<title>Basic test for the user-find property</title>
|
||||
<body>
|
||||
<script>
|
||||
const t = async_test("Basic test for the user-find property");
|
||||
|
||||
function testFindable(findCount, textToFind, buildDoc, description) {
|
||||
if (typeof findCount == "boolean")
|
||||
findCount = findCount ? 1 : 0;
|
||||
try {
|
||||
const iframe = document.querySelector("iframe")
|
||||
iframe.contentDocument.documentElement.innerHTML =
|
||||
(typeof buildDoc == "string") ? buildDoc : "";
|
||||
|
||||
if (typeof buildDoc == "function")
|
||||
buildDoc(iframe.contentDocument);
|
||||
|
||||
iframe.contentWindow.getSelection().removeAllRanges();
|
||||
for (let i = findCount; i >= 0; --i) {
|
||||
const expectFindable = i != 0;
|
||||
assert_equals(
|
||||
iframe.contentWindow.find(textToFind),
|
||||
expectFindable,
|
||||
"Should be " + (expectFindable ? "" : "not ") + "findable: " + description + ", text: " + textToFind + ", iter: " + (findCount - i + 1)
|
||||
);
|
||||
}
|
||||
} catch (ex) {
|
||||
assert_unreached(ex);
|
||||
}
|
||||
}
|
||||
|
||||
let runTests = t.step_func_done(function() {
|
||||
testFindable(true, "me", `
|
||||
Find me please
|
||||
`, "sanity test");
|
||||
|
||||
testFindable(false, "me", `
|
||||
<div style="user-find: none">Do not find me please</div>
|
||||
`, "Basic use case");
|
||||
|
||||
testFindable(true, "me", `
|
||||
<div style="user-find: none">Do not find me, but <span style="user-find: auto">find me please</span></div>
|
||||
`, "nested");
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.onload = runTests;
|
||||
iframe.srcdoc = "<!doctype html><html></html>";
|
||||
document.body.appendChild(iframe);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -140,7 +140,7 @@ static bool IsRubyAnnotationNode(const nsINode* aNode) {
|
|||
StyleDisplay::RubyTextContainer == display;
|
||||
}
|
||||
|
||||
static bool IsVisibleNode(const nsINode* aNode) {
|
||||
static bool IsFindableNode(const nsINode* aNode) {
|
||||
if (!IsDisplayedNode(aNode)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -151,7 +151,8 @@ static bool IsVisibleNode(const nsINode* aNode) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (frame->HidesContent(nsIFrame::IncludeContentVisibility::Hidden) ||
|
||||
if (frame->StyleUI()->UserFind() == StyleUserFind::None ||
|
||||
frame->HidesContent(nsIFrame::IncludeContentVisibility::Hidden) ||
|
||||
frame->IsHiddenByContentVisibilityOnAnyAncestor(
|
||||
nsIFrame::IncludeContentVisibility::Hidden)) {
|
||||
return false;
|
||||
|
|
@ -953,8 +954,8 @@ nsFind::Find(const nsAString& aPatText, nsRange* aSearchRange,
|
|||
}
|
||||
|
||||
RefPtr<nsRange> range = nsRange::Create(current);
|
||||
if (startParent && endParent && IsVisibleNode(startParent) &&
|
||||
IsVisibleNode(endParent)) {
|
||||
if (startParent && endParent && IsFindableNode(startParent) &&
|
||||
IsFindableNode(endParent)) {
|
||||
IgnoredErrorResult rv;
|
||||
range->SetStart(*startParent, matchStartOffset, rv);
|
||||
if (!rv.Failed()) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue