Bug 1637476 - Build the ::placeholder's DisplayLists first so that it doesn't obscure the caret. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D75252
This commit is contained in:
Mats Palmgren 2020-05-20 18:15:55 +00:00
parent bcc6380424
commit ebfa4831f9
9 changed files with 185 additions and 17 deletions

View File

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>Reference: Caret is correctly painted with placeholder opacity:1</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
input {
-webkit-appearance:none; /* to avoid bug 1637804 */
/* reset any UA styles and use colors that won't trigger anti-aliasing issues */
background: white;
border: 1px solid black;
outline: 1px solid black;
}
</style>
<input>
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('input').focus();
requestAnimationFrame(function() {
requestAnimationFrame(function() {
document.documentElement.removeAttribute("class");
});
});
});
</script>

View File

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>Caret is correctly painted with placeholder opacity:1</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
input::placeholder {
background: white;
opacity: 1;
}
input {
-webkit-appearance:none; /* to avoid bug 1637804 */
/* reset any UA styles and use colors that won't trigger anti-aliasing issues */
background: white;
border: 1px solid black;
outline: 1px solid black;
}
</style>
<input placeholder="&nbsp;">
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('input').focus();
setTimeout(function(){document.documentElement.removeAttribute("class");}, 0);
});
</script>

View File

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>Reference: Caret is correctly painted with placeholder opacity:1</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
input {
-webkit-appearance:none; /* to avoid bug 1637804 */
/* reset any UA styles and use colors that won't trigger anti-aliasing issues */
background: white;
border: 1px solid black;
outline: 1px solid black;
}
</style>
<input type=password>
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('input').focus();
requestAnimationFrame(function() {
requestAnimationFrame(function() {
document.documentElement.removeAttribute("class");
});
});
});
</script>

View File

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>Caret is correctly painted with placeholder opacity:1</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
input::placeholder {
background: white;
opacity: 1;
}
input {
-webkit-appearance:none; /* to avoid bug 1637804 */
/* reset any UA styles and use colors that won't trigger anti-aliasing issues */
background: white;
border: 1px solid black;
outline: 1px solid black;
}
</style>
<input type=password placeholder="&nbsp;">
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('input').focus();
setTimeout(function(){document.documentElement.removeAttribute("class");}, 0);
});
</script>

View File

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>Reference: Caret is correctly painted with placeholder opacity:1</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
input {
-webkit-appearance:none; /* to avoid bug 1637804 */
/* reset any UA styles and use colors that won't trigger anti-aliasing issues */
background: white;
border: 1px solid black;
outline: 1px solid black;
}
</style>
<input type=number>
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('input').focus();
requestAnimationFrame(function() {
requestAnimationFrame(function() {
document.documentElement.removeAttribute("class");
});
});
});
</script>

View File

@ -0,0 +1,24 @@
<!doctype html>
<html class="reftest-wait">
<title>Caret is correctly painted with placeholder opacity:1</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<style>
input::placeholder {
background: white;
opacity: 1;
}
input {
-webkit-appearance:none; /* to avoid bug 1637804 */
/* reset any UA styles and use colors that won't trigger anti-aliasing issues */
background: white;
border: 1px solid black;
outline: 1px solid black;
}
</style>
<input type=number placeholder="&nbsp;">
<script>
SimpleTest.waitForFocus(function() {
document.querySelector('input').focus();
setTimeout(function(){document.documentElement.removeAttribute("class");}, 0);
});
</script>

View File

@ -363,6 +363,12 @@ support-files =
bug1634543-4.html
bug1634743-1.html
bug1634743-1-ref.html
bug1637476-1.html
bug1637476-1-ref.html
bug1637476-2.html
bug1637476-2-ref.html
bug1637476-3.html
bug1637476-3-ref.html
image_rgrg-256x256.png
input-invalid-ref.html
input-maxlength-invalid-change.html

View File

@ -271,6 +271,9 @@ var tests = [
[ 'bug1634543-4.html' , 'bug1634543-1-ref.html' ] ,
// Caret + line-height + pseudo-element only.
[ 'bug1634743-1.html' , 'bug1634743-1-ref.html' ] ,
[ 'bug1637476-1.html' , 'bug1637476-1-ref.html' ] ,
[ 'bug1637476-2.html' , 'bug1637476-2-ref.html' ] ,
[ 'bug1637476-3.html' , 'bug1637476-3-ref.html' ] ,
function() {SpecialPowers.pushPrefEnv({'clear': [['layout.accessiblecaret.enabled_on_touch']]}, nextTest);} ,
function() {SpecialPowers.pushPrefEnv({'set': [['accessibility.browsewithcaret', true]]}, nextTest);} ,
[ 'bug1529492-1.html' , 'bug1529492-1-ref.html' ] ,

View File

@ -1290,29 +1290,44 @@ void nsTextControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsDisplayList* content = aLists.Content();
nsDisplayListSet set(content, content, content, content, content, content);
for (nsIFrame* kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) {
// Clip the placeholder and preview text to the root box, so that it doesn't,
// e.g., overlay with our <input type="number"> spin buttons.
//
// For other input types, this will be a noop since we size the root via
// ReflowTextControlChild, which sets the same available space for all
// children.
auto clipToRoot = [&](Maybe<DisplayListClipState::AutoSaveRestore>& aClip) {
if (mRootNode) {
if (auto* root = mRootNode->GetPrimaryFrame()) {
aClip.emplace(aBuilder);
nsRect rootBox(aBuilder->ToReferenceFrame(root), root->GetSize());
aClip->ClipContentDescendants(rootBox);
}
}
};
// We build the ::placeholder first so that it renders below mRootNode which
// draws the caret and we always want that on top (bug 1637476).
if (mPlaceholderDiv && control->GetPlaceholderVisibility() &&
mPlaceholderDiv->GetPrimaryFrame()) {
Maybe<DisplayListClipState::AutoSaveRestore> overlayTextClip;
clipToRoot(overlayTextClip);
auto* kid = mPlaceholderDiv->GetPrimaryFrame();
MOZ_ASSERT(kid->GetParent() == this);
BuildDisplayListForChild(aBuilder, kid, set, 0);
}
for (auto* kid : mFrames) {
nsIContent* kidContent = kid->GetContent();
Maybe<DisplayListClipState::AutoSaveRestore> overlayTextClip;
if (kidContent == mPlaceholderDiv && !control->GetPlaceholderVisibility()) {
continue;
if (kidContent == mPlaceholderDiv) {
continue; // we handled mPlaceholderDiv explicitly above
}
if (kidContent == mPreviewDiv && !control->GetPreviewVisibility()) {
continue;
}
// Clip the preview text to the root box, so that it doesn't, e.g., overlay
// with our <input type="number"> spin buttons.
//
// For other input types, this will be a noop since we size the root via
// ReflowTextControlChild, which sets the same available space for all
// children.
if (kidContent == mPlaceholderDiv || kidContent == mPreviewDiv) {
if (mRootNode) {
if (auto* root = mRootNode->GetPrimaryFrame()) {
overlayTextClip.emplace(aBuilder);
nsRect rootBox(aBuilder->ToReferenceFrame(root), root->GetSize());
overlayTextClip->ClipContentDescendants(rootBox);
}
}
if (kidContent == mPreviewDiv) {
clipToRoot(overlayTextClip);
}
BuildDisplayListForChild(aBuilder, kid, set, 0);
}