From 5786b9be9f887ed371c804e786081b476a403104 Mon Sep 17 00:00:00 2001 From: Narcis Beleuzu Date: Sun, 7 Oct 2018 05:14:44 +0300 Subject: [PATCH] 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) --- layout/forms/nsFileControlFrame.cpp | 183 ++---------------- layout/forms/nsFileControlFrame.h | 29 +-- layout/generic/nsTextFrame.cpp | 22 --- layout/generic/nsTextFrame.h | 7 - .../input/file/dynamic-max-width-ref.html | 20 -- .../forms/input/file/dynamic-max-width.html | 34 ---- layout/reftests/forms/input/file/reftest.list | 1 - layout/style/res/forms.css | 20 +- 8 files changed, 35 insertions(+), 281 deletions(-) delete mode 100644 layout/reftests/forms/input/file/dynamic-max-width-ref.html delete mode 100644 layout/reftests/forms/input/file/dynamic-max-width.html diff --git a/layout/forms/nsFileControlFrame.cpp b/layout/forms/nsFileControlFrame.cpp index 46a273baf064..61a77685e19d 100644 --- a/layout/forms/nsFileControlFrame.cpp +++ b/layout/forms/nsFileControlFrame.cpp @@ -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 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& aElements) } // Create and setup the text showing the selected files. - mTextContent = doc->CreateHTMLElement(nsGkAtoms::label); + RefPtr 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 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(text->GetPrimaryFrame())) { - textFrame->NotifyNativeAnonymousTextnodeChange(oldLength); - } - } + mTextContent->SetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue, aNotify); } nsresult diff --git a/layout/forms/nsFileControlFrame.h b/layout/forms/nsFileControlFrame.h index 052d42c887f0..6ec437b0efe6 100644 --- a/layout/forms/nsFileControlFrame.h +++ b/layout/forms/nsFileControlFrame.h @@ -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 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. */ diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 966efb56c6c0..af6fddb77651 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -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) { diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 627ef94dc34f..af0a9ab14a81 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -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(); diff --git a/layout/reftests/forms/input/file/dynamic-max-width-ref.html b/layout/reftests/forms/input/file/dynamic-max-width-ref.html deleted file mode 100644 index 1628c5fa3011..000000000000 --- a/layout/reftests/forms/input/file/dynamic-max-width-ref.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Reference for dynamic-max-width.html - - - - - -
- - - - - - diff --git a/layout/reftests/forms/input/file/dynamic-max-width.html b/layout/reftests/forms/input/file/dynamic-max-width.html deleted file mode 100644 index 1cad23c16983..000000000000 --- a/layout/reftests/forms/input/file/dynamic-max-width.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CSS Test: file control with dynamic change to max-width - - - - - - - -
- - - - - - diff --git a/layout/reftests/forms/input/file/reftest.list b/layout/reftests/forms/input/file/reftest.list index 2aaf8e54713b..0823af6a6a1c 100644 --- a/layout/reftests/forms/input/file/reftest.list +++ b/layout/reftests/forms/input/file/reftest.list @@ -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 diff --git a/layout/style/res/forms.css b/layout/style/res/forms.css index abb84ea89c7f..70aaf63e9335 100644 --- a/layout/style/res/forms.css +++ b/layout/style/res/forms.css @@ -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 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;