зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1495153) for causing perma failures on dynamic-max-width.html
Backed out changeset 6d95f0e0cc76 (bug 1495153) Backed out changeset 6800eb348ebe (bug 1495153)
This commit is contained in:
Родитель
18849ef0ae
Коммит
5786b9be9f
|
@ -27,7 +27,6 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "nsTextNode.h"
|
||||
#include "nsTextFrame.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -57,144 +56,6 @@ nsFileControlFrame::Init(nsIContent* aContent,
|
|||
mMouseListener = new DnDListener(this);
|
||||
}
|
||||
|
||||
bool
|
||||
nsFileControlFrame::CropTextToWidth(gfxContext& aRenderingContext,
|
||||
const nsIFrame* aFrame,
|
||||
nscoord aWidth,
|
||||
nsString& aText)
|
||||
{
|
||||
if (aText.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<nsFontMetrics> fm =
|
||||
nsLayoutUtils::GetFontMetricsForFrame(aFrame, 1.0f);
|
||||
|
||||
// see if the text will completely fit in the width given
|
||||
nscoord textWidth =
|
||||
nsLayoutUtils::AppUnitWidthOfStringBidi(aText, aFrame, *fm,
|
||||
aRenderingContext);
|
||||
if (textWidth <= aWidth) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
|
||||
const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
|
||||
|
||||
// see if the width is even smaller than the ellipsis
|
||||
fm->SetTextRunRTL(false);
|
||||
textWidth = nsLayoutUtils::AppUnitWidthOfString(kEllipsis, *fm, drawTarget);
|
||||
if (textWidth >= aWidth) {
|
||||
aText = kEllipsis;
|
||||
return true;
|
||||
}
|
||||
|
||||
// determine how much of the string will fit in the max width
|
||||
nscoord totalWidth = textWidth;
|
||||
using mozilla::unicode::ClusterIterator;
|
||||
using mozilla::unicode::ClusterReverseIterator;
|
||||
ClusterIterator leftIter(aText.Data(), aText.Length());
|
||||
ClusterReverseIterator rightIter(aText.Data(), aText.Length());
|
||||
const char16_t* leftPos = leftIter;
|
||||
const char16_t* rightPos = rightIter;
|
||||
const char16_t* pos;
|
||||
ptrdiff_t length;
|
||||
nsAutoString leftString, rightString;
|
||||
|
||||
while (leftPos < rightPos) {
|
||||
leftIter.Next();
|
||||
pos = leftIter;
|
||||
length = pos - leftPos;
|
||||
textWidth = nsLayoutUtils::AppUnitWidthOfString(leftPos, length,
|
||||
*fm, drawTarget);
|
||||
if (totalWidth + textWidth > aWidth) {
|
||||
break;
|
||||
}
|
||||
|
||||
leftString.Append(leftPos, length);
|
||||
leftPos = pos;
|
||||
totalWidth += textWidth;
|
||||
|
||||
if (leftPos >= rightPos) {
|
||||
break;
|
||||
}
|
||||
|
||||
rightIter.Next();
|
||||
pos = rightIter;
|
||||
length = rightPos - pos;
|
||||
textWidth = nsLayoutUtils::AppUnitWidthOfString(pos, length,
|
||||
*fm, drawTarget);
|
||||
if (totalWidth + textWidth > aWidth) {
|
||||
break;
|
||||
}
|
||||
|
||||
rightString.Insert(pos, 0, length);
|
||||
rightPos = pos;
|
||||
totalWidth += textWidth;
|
||||
}
|
||||
|
||||
aText = leftString + kEllipsis + rightString;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsFileControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
ReflowOutput& aMetrics,
|
||||
const ReflowInput& aReflowInput,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
// Restore the uncropped filename.
|
||||
nsAutoString filename;
|
||||
HTMLInputElement::FromNode(mContent)->GetDisplayFileName(filename);
|
||||
|
||||
bool done = false;
|
||||
while (true) {
|
||||
UpdateDisplayedValue(filename, false); // update the text node
|
||||
AddStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||
LinesBegin()->MarkDirty();
|
||||
nsBlockFrame::Reflow(aPresContext, aMetrics, aReflowInput, aStatus);
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
nscoord lineISize = LinesBegin()->ISize();
|
||||
const auto cbWM = aMetrics.GetWritingMode();
|
||||
const auto wm = GetWritingMode();
|
||||
nscoord iSize = wm.IsOrthogonalTo(cbWM) ? aMetrics.BSize(cbWM)
|
||||
: aMetrics.ISize(cbWM);
|
||||
auto bp = GetLogicalUsedBorderAndPadding(wm);
|
||||
nscoord contentISize = iSize - bp.IStartEnd(wm);
|
||||
if (lineISize > contentISize) {
|
||||
// The filename overflows - crop it and reflow again (once).
|
||||
// NOTE: the label frame might have bidi-continuations
|
||||
auto* labelFrame = mTextContent->GetPrimaryFrame();
|
||||
nscoord labelBP =
|
||||
labelFrame->GetLogicalUsedBorderAndPadding(wm).IStartEnd(wm);
|
||||
auto* lastLabelCont = labelFrame->LastContinuation();
|
||||
if (lastLabelCont != labelFrame) {
|
||||
labelBP +=
|
||||
lastLabelCont->GetLogicalUsedBorderAndPadding(wm).IStartEnd(wm);
|
||||
}
|
||||
auto* buttonFrame = mBrowseFilesOrDirs->GetPrimaryFrame();
|
||||
nscoord availableISizeForLabel = contentISize - buttonFrame->ISize(wm) -
|
||||
buttonFrame->GetLogicalUsedMargin(wm).IStartEnd(wm);
|
||||
if (CropTextToWidth(*aReflowInput.mRenderingContext,
|
||||
labelFrame,
|
||||
availableISizeForLabel - labelBP,
|
||||
filename)) {
|
||||
nsBlockFrame::DidReflow(aPresContext, &aReflowInput);
|
||||
aStatus.Reset();
|
||||
labelFrame->AddStateBits(NS_FRAME_IS_DIRTY |
|
||||
NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||
mMinWidth = NS_INTRINSIC_WIDTH_UNKNOWN;
|
||||
mPrefWidth = NS_INTRINSIC_WIDTH_UNKNOWN;
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFileControlFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
|
||||
{
|
||||
|
@ -280,19 +141,25 @@ nsFileControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
|||
}
|
||||
|
||||
// Create and setup the text showing the selected files.
|
||||
mTextContent = doc->CreateHTMLElement(nsGkAtoms::label);
|
||||
RefPtr<NodeInfo> nodeInfo;
|
||||
nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::label, nullptr,
|
||||
kNameSpaceID_XUL,
|
||||
nsINode::ELEMENT_NODE);
|
||||
NS_TrustedNewXULElement(getter_AddRefs(mTextContent), nodeInfo.forget());
|
||||
// NOTE: SetIsNativeAnonymousRoot() has to be called before setting any
|
||||
// attribute.
|
||||
mTextContent->SetIsNativeAnonymousRoot();
|
||||
RefPtr<nsTextNode> text = new nsTextNode(doc->NodeInfoManager());
|
||||
mTextContent->AppendChildTo(text, false);
|
||||
mTextContent->SetAttr(kNameSpaceID_None, nsGkAtoms::crop,
|
||||
NS_LITERAL_STRING("center"), false);
|
||||
|
||||
// Update the displayed text to reflect the current element's value.
|
||||
nsAutoString value;
|
||||
HTMLInputElement::FromNode(mContent)->GetDisplayFileName(value);
|
||||
UpdateDisplayedValue(value, false);
|
||||
|
||||
aElements.AppendElement(mTextContent);
|
||||
if (!aElements.AppendElement(mTextContent)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// We should be able to interact with the element by doing drag and drop.
|
||||
mContent->AddSystemEventListener(NS_LITERAL_STRING("drop"),
|
||||
|
@ -549,7 +416,7 @@ nsFileControlFrame::DnDListener::CanDropTheseFiles(DataTransfer* aDataTransfer,
|
|||
}
|
||||
|
||||
nscoord
|
||||
nsFileControlFrame::GetMinISize(gfxContext* aRenderingContext)
|
||||
nsFileControlFrame::GetMinISize(gfxContext *aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_MIN_INLINE_SIZE(this, result);
|
||||
|
@ -559,23 +426,6 @@ nsFileControlFrame::GetMinISize(gfxContext* aRenderingContext)
|
|||
return result;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFileControlFrame::GetPrefISize(gfxContext* aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_MIN_INLINE_SIZE(this, result);
|
||||
|
||||
// Make sure we measure with the uncropped filename.
|
||||
if (mPrefWidth == NS_INTRINSIC_WIDTH_UNKNOWN) {
|
||||
nsAutoString filename;
|
||||
HTMLInputElement::FromNode(mContent)->GetDisplayFileName(filename);
|
||||
UpdateDisplayedValue(filename, false);
|
||||
}
|
||||
|
||||
result = nsBlockFrame::GetPrefISize(aRenderingContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsFileControlFrame::SyncDisabledState()
|
||||
{
|
||||
|
@ -625,16 +475,7 @@ nsFileControlFrame::GetFrameName(nsAString& aResult) const
|
|||
void
|
||||
nsFileControlFrame::UpdateDisplayedValue(const nsAString& aValue, bool aNotify)
|
||||
{
|
||||
auto* text = Text::FromNode(mTextContent->GetFirstChild());
|
||||
uint32_t oldLength = aNotify ? 0 : text->TextLength();
|
||||
text->SetText(aValue, aNotify);
|
||||
if (!aNotify) {
|
||||
// We can't notify during Reflow so we need to tell the text frame
|
||||
// about the text content change we just did.
|
||||
if (auto* textFrame = static_cast<nsTextFrame*>(text->GetPrimaryFrame())) {
|
||||
textFrame->NotifyNativeAnonymousTextnodeChange(oldLength);
|
||||
}
|
||||
}
|
||||
mTextContent->SetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -27,29 +27,23 @@ class nsFileControlFrame final : public nsBlockFrame,
|
|||
public nsIAnonymousContentCreator
|
||||
{
|
||||
public:
|
||||
NS_DECL_QUERYFRAME
|
||||
NS_DECL_FRAMEARENA_HELPERS(nsFileControlFrame)
|
||||
|
||||
explicit nsFileControlFrame(ComputedStyle* aStyle);
|
||||
|
||||
virtual void Init(nsIContent* aContent,
|
||||
nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) override;
|
||||
|
||||
void Reflow(nsPresContext* aPresContext,
|
||||
ReflowOutput& aDesiredSize,
|
||||
const ReflowInput& aReflowInput,
|
||||
nsReflowStatus& aStatus) override;
|
||||
|
||||
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) override;
|
||||
|
||||
NS_DECL_QUERYFRAME
|
||||
NS_DECL_FRAMEARENA_HELPERS(nsFileControlFrame)
|
||||
|
||||
// nsIFormControlFrame
|
||||
virtual nsresult SetFormProperty(nsAtom* aName, const nsAString& aValue) override;
|
||||
virtual void SetFocus(bool aOn, bool aRepaint) override;
|
||||
|
||||
nscoord GetMinISize(gfxContext* aRenderingContext) override;
|
||||
nscoord GetPrefISize(gfxContext* aRenderingContext) override;
|
||||
virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
|
||||
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
|
||||
|
||||
|
@ -57,9 +51,9 @@ public:
|
|||
virtual nsresult GetFrameName(nsAString& aResult) const override;
|
||||
#endif
|
||||
|
||||
nsresult AttributeChanged(int32_t aNameSpaceID,
|
||||
nsAtom* aAttribute,
|
||||
int32_t aModType) override;
|
||||
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
|
||||
nsAtom* aAttribute,
|
||||
int32_t aModType) override;
|
||||
virtual void ContentStatesChanged(mozilla::EventStates aStates) override;
|
||||
|
||||
// nsIAnonymousContentCreator
|
||||
|
@ -157,15 +151,6 @@ protected:
|
|||
RefPtr<DnDListener> mMouseListener;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Crop aText to fit inside aWidth using the styles of aFrame.
|
||||
* @return true if aText was modified
|
||||
*/
|
||||
static bool CropTextToWidth(gfxContext& aRenderingContext,
|
||||
const nsIFrame* aFrame,
|
||||
nscoord aWidth,
|
||||
nsString& aText);
|
||||
|
||||
/**
|
||||
* Sync the disabled state of the content with anonymous children.
|
||||
*/
|
||||
|
|
|
@ -4796,28 +4796,6 @@ nsTextFrame::DisconnectTextRuns()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFrame::NotifyNativeAnonymousTextnodeChange(uint32_t aOldLength)
|
||||
{
|
||||
MOZ_ASSERT(mContent->IsInNativeAnonymousSubtree());
|
||||
|
||||
MarkIntrinsicISizesDirty();
|
||||
|
||||
// This is to avoid making a new Reflow request in CharacterDataChanged:
|
||||
for (nsTextFrame* f = this; f; f = f->GetNextContinuation()) {
|
||||
f->AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
f->mReflowRequestedForCharDataChange = true;
|
||||
}
|
||||
|
||||
// Pretend that all the text changed.
|
||||
CharacterDataChangeInfo info;
|
||||
info.mAppend = false;
|
||||
info.mChangeStart = 0;
|
||||
info.mChangeEnd = aOldLength;
|
||||
info.mReplaceLength = mContent->TextLength();
|
||||
CharacterDataChanged(info);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTextFrame::CharacterDataChanged(const CharacterDataChangeInfo& aInfo)
|
||||
{
|
||||
|
|
|
@ -668,13 +668,6 @@ public:
|
|||
|
||||
bool HasAnyNoncollapsedCharacters() override;
|
||||
|
||||
/**
|
||||
* Call this after you have manually changed the text node contents without
|
||||
* notifying that change. This behaves as if all the text contents changed.
|
||||
* (You should only use this for native anonymous content.)
|
||||
*/
|
||||
void NotifyNativeAnonymousTextnodeChange(uint32_t aOldLength);
|
||||
|
||||
protected:
|
||||
virtual ~nsTextFrame();
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html><head>
|
||||
<meta charset="utf-8">
|
||||
<title>Reference for dynamic-max-width.html</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<input type=file dir=rtl>
|
||||
|
||||
<br>
|
||||
|
||||
<input type=file>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html class="reftest-wait"><head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Test: file control with dynamic change to max-width</title>
|
||||
<style type="text/css">
|
||||
|
||||
input { max-width: 10em; }
|
||||
|
||||
</style>
|
||||
<script>
|
||||
function tweak() {
|
||||
[...document.querySelectorAll('input')].forEach(function(e) {
|
||||
e.style.maxWidth = 'initial';
|
||||
});
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
window.addEventListener("MozReftestInvalidate", tweak);
|
||||
</script>
|
||||
</head>
|
||||
<body onload="test()">
|
||||
|
||||
<input type=file dir=rtl>
|
||||
|
||||
<br>
|
||||
|
||||
<input type=file>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -5,4 +5,3 @@ fuzzy-if(gtkWidget||webrender,0-1,0-10) fails-if(Android) == background.html bac
|
|||
fuzzy-if(gtkWidget,0-1,0-10) fails-if(Android) == style.html style-ref.xul
|
||||
!= width-clip.html width-clip-ref.html
|
||||
fails-if(Android) == color-inherit.html color-inherit-ref.html
|
||||
fuzzy-if(Android,1-2,2-2) == dynamic-max-width.html dynamic-max-width-ref.html
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
|
||||
@namespace url(http://www.w3.org/1999/xhtml); /* set default namespace to HTML */
|
||||
@namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);
|
||||
|
||||
*|*::-moz-fieldset-content {
|
||||
display: block; /* StyleAdjuster::adjust_for_fieldset_content overrides this in some cases */
|
||||
|
@ -479,7 +480,7 @@ input[type="image"]:-moz-focusring {
|
|||
/* file selector */
|
||||
input[type="file"] {
|
||||
display: inline-block;
|
||||
white-space: nowrap !important;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
overflow-clip-box: padding-box;
|
||||
color: unset;
|
||||
|
@ -494,7 +495,7 @@ input[type="file"] {
|
|||
padding: unset;
|
||||
}
|
||||
|
||||
input[type="file"] > label {
|
||||
input[type="file"] > xul|label {
|
||||
min-inline-size: 12em;
|
||||
padding-inline-start: 5px;
|
||||
text-align: match-parent;
|
||||
|
@ -503,8 +504,11 @@ input[type="file"] > label {
|
|||
font-size: unset;
|
||||
letter-spacing: unset;
|
||||
|
||||
-moz-user-select: none;
|
||||
unicode-bidi: plaintext;
|
||||
/*
|
||||
* Force the text to have LTR directionality. Otherwise filenames containing
|
||||
* RTL characters will be reordered with chaotic results.
|
||||
*/
|
||||
direction: ltr !important;
|
||||
}
|
||||
|
||||
/* button part of file selector */
|
||||
|
@ -528,6 +532,14 @@ input[type="color"]::-moz-color-swatch {
|
|||
display: block;
|
||||
}
|
||||
|
||||
/* Try to make RTL <input type='file'> look nicer. */
|
||||
/* TODO: find a better solution than forcing direction: ltr on all file
|
||||
input labels and remove this override -- bug 1161482 */
|
||||
input[type="file"]:dir(rtl) > xul|label {
|
||||
padding-inline-start: 0px;
|
||||
padding-inline-end: 5px;
|
||||
}
|
||||
|
||||
/* radio buttons */
|
||||
input[type="radio"] {
|
||||
display: inline-block;
|
||||
|
|
Загрузка…
Ссылка в новой задаче