Bug 1340483 - Part 4. Update input visibility accordingly. r=heycam
MozReview-Commit-ID: 7eBhj7w4qhP
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -2868,21 +2868,21 @@ HTMLInputElement::GetPlaceholderNode()
nsTextEditorState* state = GetEditorState();
if (state) {
return state->GetPlaceholderNode();
}
return nullptr;
}
NS_IMETHODIMP_(void)
-HTMLInputElement::UpdatePlaceholderVisibility(bool aNotify)
+HTMLInputElement::UpdateOverlayTextVisibility(bool aNotify)
{
nsTextEditorState* state = GetEditorState();
if (state) {
- state->UpdatePlaceholderVisibility(aNotify);
+ state->UpdateOverlayTextVisibility(aNotify);
}
}
NS_IMETHODIMP_(bool)
HTMLInputElement::GetPlaceholderVisibility()
{
nsTextEditorState* state = GetEditorState();
if (!state) {
@@ -2944,16 +2944,27 @@ HTMLInputElement::EnablePreview()
}
NS_IMETHODIMP_(bool)
HTMLInputElement::IsPreviewEnabled()
{
return mIsPreviewEnabled;
}
+NS_IMETHODIMP_(bool)
+HTMLInputElement::GetPreviewVisibility()
+{
+ nsTextEditorState* state = GetEditorState();
+ if (!state) {
+ return false;
+ }
+
+ return state->GetPreviewVisibility();
+}
+
void
HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
{
if (OwnerDoc()->IsStaticDocument()) {
aValue = mStaticDocFileList;
return;
}
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -231,22 +231,23 @@ public:
NS_IMETHOD BindToFrame(nsTextControlFrame* aFrame) override;
NS_IMETHOD_(void) UnbindFromFrame(nsTextControlFrame* aFrame) override;
NS_IMETHOD CreateEditor() override;
NS_IMETHOD_(Element*) GetRootEditorNode() override;
NS_IMETHOD_(Element*) CreatePlaceholderNode() override;
NS_IMETHOD_(Element*) GetPlaceholderNode() override;
NS_IMETHOD_(Element*) CreatePreviewNode() override;
NS_IMETHOD_(Element*) GetPreviewNode() override;
- NS_IMETHOD_(void) UpdatePlaceholderVisibility(bool aNotify) override;
+ NS_IMETHOD_(void) UpdateOverlayTextVisibility(bool aNotify) override;
NS_IMETHOD_(void) SetPreviewValue(const nsAString& aValue) override;
NS_IMETHOD_(void) GetPreviewValue(nsAString& aValue) override;
NS_IMETHOD_(void) EnablePreview() override;
NS_IMETHOD_(bool) IsPreviewEnabled() override;
NS_IMETHOD_(bool) GetPlaceholderVisibility() override;
+ NS_IMETHOD_(bool) GetPreviewVisibility() override;
NS_IMETHOD_(void) InitializeKeyboardEventListeners() override;
NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) override;
virtual void GetValueFromSetRangeText(nsAString& aValue) override;
virtual nsresult SetValueFromSetRangeText(const nsAString& aValue) override;
NS_IMETHOD_(bool) HasCachedSelection() override;
// Methods for nsFormFillController so it can do selection operations on input
// types the HTML spec doesn't support them on, like "email".
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -305,19 +305,19 @@ HTMLTextAreaElement::CreatePlaceholderNo
NS_IMETHODIMP_(Element*)
HTMLTextAreaElement::GetPlaceholderNode()
{
return mState.GetPlaceholderNode();
}
NS_IMETHODIMP_(void)
-HTMLTextAreaElement::UpdatePlaceholderVisibility(bool aNotify)
+HTMLTextAreaElement::UpdateOverlayTextVisibility(bool aNotify)
{
- mState.UpdatePlaceholderVisibility(aNotify);
+ mState.UpdateOverlayTextVisibility(aNotify);
}
NS_IMETHODIMP_(bool)
HTMLTextAreaElement::GetPlaceholderVisibility()
{
return mState.GetPlaceholderVisibility();
}
@@ -359,16 +359,22 @@ HTMLTextAreaElement::EnablePreview()
}
NS_IMETHODIMP_(bool)
HTMLTextAreaElement::IsPreviewEnabled()
{
return mIsPreviewEnabled;
}
+NS_IMETHODIMP_(bool)
+HTMLTextAreaElement::GetPreviewVisibility()
+{
+ return mState.GetPreviewVisibility();
+}
+
nsresult
HTMLTextAreaElement::SetValueInternal(const nsAString& aValue,
uint32_t aFlags)
{
// Need to set the value changed flag here if our value has in fact changed
// (i.e. if eSetValue_Notify is in aFlags), so that
// nsTextControlFrame::UpdateValueDisplay retrieves the correct value if
// needed.
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -100,18 +100,19 @@ public:
NS_IMETHOD BindToFrame(nsTextControlFrame* aFrame) override;
NS_IMETHOD_(void) UnbindFromFrame(nsTextControlFrame* aFrame) override;
NS_IMETHOD CreateEditor() override;
NS_IMETHOD_(Element*) GetRootEditorNode() override;
NS_IMETHOD_(Element*) CreatePlaceholderNode() override;
NS_IMETHOD_(Element*) GetPlaceholderNode() override;
NS_IMETHOD_(Element*) CreatePreviewNode() override;
NS_IMETHOD_(Element*) GetPreviewNode() override;
- NS_IMETHOD_(void) UpdatePlaceholderVisibility(bool aNotify) override;
+ NS_IMETHOD_(void) UpdateOverlayTextVisibility(bool aNotify) override;
NS_IMETHOD_(bool) GetPlaceholderVisibility() override;
+ NS_IMETHOD_(bool) GetPreviewVisibility() override;
NS_IMETHOD_(void) SetPreviewValue(const nsAString& aValue) override;
NS_IMETHOD_(void) GetPreviewValue(nsAString& aValue) override;
NS_IMETHOD_(void) EnablePreview() override;
NS_IMETHOD_(bool) IsPreviewEnabled() override;
NS_IMETHOD_(void) InitializeKeyboardEventListeners() override;
NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) override;
virtual void GetValueFromSetRangeText(nsAString& aValue) override;
virtual nsresult SetValueFromSetRangeText(const nsAString& aValue) override;
--- a/dom/html/nsITextControlElement.h
+++ b/dom/html/nsITextControlElement.h
@@ -185,26 +185,31 @@ public:
NS_IMETHOD_(bool) IsPreviewEnabled() = 0;
/**
* Initialize the keyboard event listeners.
*/
NS_IMETHOD_(void) InitializeKeyboardEventListeners() = 0;
/**
- * Update the placeholder visibility based on the element's state.
+ * Update the visibility of both the placholder and preview text based on the element's state.
*/
- NS_IMETHOD_(void) UpdatePlaceholderVisibility(bool aNotify) = 0;
+ NS_IMETHOD_(void) UpdateOverlayTextVisibility(bool aNotify) = 0;
/**
* Returns the current expected placeholder visibility state.
*/
NS_IMETHOD_(bool) GetPlaceholderVisibility() = 0;
/**
+ * Returns the current expected preview visibility state.
+ */
+ NS_IMETHOD_(bool) GetPreviewVisibility() = 0;
+
+ /**
* Callback called whenever the value is changed.
*/
NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) = 0;
/**
* Helpers for value manipulation from SetRangeText.
*/
virtual void GetValueFromSetRangeText(nsAString& aValue) = 0;
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -1062,16 +1062,17 @@ nsTextEditorState::nsTextEditorState(nsI
, mBoundFrame(nullptr)
, mEverInited(false)
, mEditorInitialized(false)
, mInitializing(false)
, mValueTransferInProgress(false)
, mSelectionCached(true)
, mSelectionRestoreEagerInit(false)
, mPlaceholderVisibility(false)
+ , mPreviewVisibility(false)
, mIsCommittingComposition(false)
// When adding more member variable initializations here, add the same
// also to ::Construct.
{
MOZ_COUNT_CTOR(nsTextEditorState);
}
nsTextEditorState*
@@ -1086,16 +1087,17 @@ nsTextEditorState::Construct(nsITextCont
state->mSelectionProperties = SelectionProperties();
state->mEverInited = false;
state->mEditorInitialized = false;
state->mInitializing = false;
state->mValueTransferInProgress = false;
state->mSelectionCached = true;
state->mSelectionRestoreEagerInit = false;
state->mPlaceholderVisibility = false;
+ state->mPreviewVisibility = false;
state->mIsCommittingComposition = false;
// When adding more member variable initializations here, add the same
// also to the constructor.
return state;
}
return new nsTextEditorState(aOwningElement);
}
@@ -2695,17 +2697,17 @@ nsTextEditorState::InitializeKeyboardEve
}
mSelCon->SetScrollableFrame(do_QueryFrame(mBoundFrame->PrincipalChildList().FirstChild()));
}
void
nsTextEditorState::ValueWasChanged(bool aNotify)
{
- UpdatePlaceholderVisibility(aNotify);
+ UpdateOverlayTextVisibility(aNotify);
}
void
nsTextEditorState::UpdatePlaceholderText(bool aNotify)
{
NS_ASSERTION(mPlaceholderDiv, "This function should not be called if "
"mPlaceholderDiv isn't set");
@@ -2732,16 +2734,18 @@ nsTextEditorState::SetPreviewText(const
if (!mPreviewDiv)
return;
nsAutoString previewValue(aValue);
nsContentUtils::RemoveNewlines(previewValue);
MOZ_ASSERT(mPreviewDiv->GetFirstChild(), "preview div has no child");
mPreviewDiv->GetFirstChild()->SetText(previewValue, aNotify);
+
+ UpdateOverlayTextVisibility(aNotify);
}
void
nsTextEditorState::GetPreviewText(nsAString& aValue)
{
// If we don't have a preview div, there's nothing to do.
if (!mPreviewDiv)
return;
@@ -2749,22 +2753,24 @@ nsTextEditorState::GetPreviewText(nsAStr
MOZ_ASSERT(mPreviewDiv->GetFirstChild(), "preview div has no child");
const nsTextFragment *text = mPreviewDiv->GetFirstChild()->GetText();
aValue.Truncate();
text->AppendTo(aValue);
}
void
-nsTextEditorState::UpdatePlaceholderVisibility(bool aNotify)
+nsTextEditorState::UpdateOverlayTextVisibility(bool aNotify)
{
- nsAutoString value;
+ nsAutoString value, previewValue;
GetValue(value, true);
-
- mPlaceholderVisibility = value.IsEmpty();
+ GetPreviewText(previewValue);
+
+ mPreviewVisibility = value.IsEmpty() && !previewValue.IsEmpty();
+ mPlaceholderVisibility = value.IsEmpty() && previewValue.IsEmpty();
if (mPlaceholderVisibility &&
!Preferences::GetBool("dom.placeholder.show_on_focus", true)) {
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
mPlaceholderVisibility = !nsContentUtils::IsFocusedContent(content);
}
if (mBoundFrame && aNotify) {
--- a/dom/html/nsTextEditorState.h
+++ b/dom/html/nsTextEditorState.h
@@ -213,27 +213,30 @@ public:
}
int32_t GetWrapCols() {
return mTextCtrlElement->GetWrapCols();
}
int32_t GetRows() {
return mTextCtrlElement->GetRows();
}
+ void UpdateOverlayTextVisibility(bool aNotify);
+
// placeholder methods
- void UpdatePlaceholderVisibility(bool aNotify);
bool GetPlaceholderVisibility() {
return mPlaceholderVisibility;
}
-
void UpdatePlaceholderText(bool aNotify);
// preview methods
void SetPreviewText(const nsAString& aValue, bool aNotify);
void GetPreviewText(nsAString& aValue);
+ bool GetPreviewVisibility() {
+ return mPreviewVisibility;
+ }
/**
* Get the maxlength attribute
* @param aMaxLength the value of the max length attr
* @returns false if attr not defined
*/
bool GetMaxLength(int32_t* aMaxLength);
@@ -445,16 +448,17 @@ private:
SelectionProperties mSelectionProperties;
bool mEverInited; // Have we ever been initialized?
bool mEditorInitialized;
bool mInitializing; // Whether we're in the process of initialization
bool mValueTransferInProgress; // Whether a value is being transferred to the frame
bool mSelectionCached; // Whether mSelectionProperties is valid
mutable bool mSelectionRestoreEagerInit; // Whether we're eager initing because of selection restore
bool mPlaceholderVisibility;
+ bool mPreviewVisibility;
bool mIsCommittingComposition;
};
inline void
ImplCycleCollectionUnlink(nsTextEditorState& aField)
{
aField.Unlink();
}
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -359,17 +359,17 @@ nsTextControlFrame::CreateAnonymousConte
// Associate ::placeholder pseudo-element with the placeholder node.
placeholderNode->SetPseudoElementType(CSSPseudoElementType::placeholder);
aElements.AppendElement(placeholderNode);
if (!IsSingleLineTextControl()) {
// For textareas, UpdateValueDisplay doesn't initialize the visibility
// status of the placeholder because it returns early, so we have to
// do that manually here.
- txtCtrl->UpdatePlaceholderVisibility(true);
+ txtCtrl->UpdateOverlayTextVisibility(true);
}
}
mUsePreview = txtCtrl->IsPreviewEnabled();
if (mUsePreview) {
// Create the preview anonymous content if needed.
Element* previewNode = txtCtrl->CreatePreviewNode();
@@ -651,17 +651,17 @@ void nsTextControlFrame::SetFocus(bool a
NS_ASSERTION(txtCtrl, "Content not a text control element");
// Revoke the previous scroll event if one exists
mScrollEvent.Revoke();
// If 'dom.placeholeder.show_on_focus' preference is 'false', focusing or
// blurring the frame can have an impact on the placeholder visibility.
if (mUsePlaceholder) {
- txtCtrl->UpdatePlaceholderVisibility(true);
+ txtCtrl->UpdateOverlayTextVisibility(true);
}
if (!aOn) {
return;
}
nsISelectionController* selCon = txtCtrl->GetSelectionController();
if (!selCon)
@@ -1178,17 +1178,17 @@ nsTextControlFrame::SetInitialChildList(
void
nsTextControlFrame::SetValueChanged(bool aValueChanged)
{
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
NS_ASSERTION(txtCtrl, "Content not a text control element");
if (mUsePlaceholder) {
AutoWeakFrame weakFrame(this);
- txtCtrl->UpdatePlaceholderVisibility(true);
+ txtCtrl->UpdateOverlayTextVisibility(true);
if (!weakFrame.IsAlive()) {
return;
}
}
txtCtrl->SetValueChanged(aValueChanged);
}
@@ -1228,23 +1228,23 @@ nsTextControlFrame::UpdateValueDisplay(b
// Get the current value of the textfield from the content.
nsAutoString value;
if (aValue) {
value = *aValue;
} else {
txtCtrl->GetTextEditorValue(value, true);
}
- // Update the display of the placeholder value if needed.
- // We don't need to do this if we're about to initialize the
- // editor, since EnsureEditorInitialized takes care of this.
- if (mUsePlaceholder && !aBeforeEditorInit)
+ // Update the display of the placeholder value and preview text if needed.
+ // We don't need to do this if we're about to initialize the editor, since
+ // EnsureEditorInitialized takes care of this.
+ if ((mUsePlaceholder || mUsePreview) && !aBeforeEditorInit)
{
AutoWeakFrame weakFrame(this);
- txtCtrl->UpdatePlaceholderVisibility(aNotify);
+ txtCtrl->UpdateOverlayTextVisibility(aNotify);
NS_ENSURE_STATE(weakFrame.IsAlive());
}
if (aBeforeEditorInit && value.IsEmpty()) {
rootNode->RemoveChildAt(0, true);
return NS_OK;
}
@@ -1350,20 +1350,22 @@ nsTextControlFrame::BuildDisplayList(nsD
nsIFrame* kid = mFrames.FirstChild();
// Redirect all lists to the Content list so that nothing can escape, ie
// opacity creating stacking contexts that then get sorted with stacking
// contexts external to us.
nsDisplayList* content = aLists.Content();
nsDisplayListSet set(content, content, content, content, content, content);
while (kid) {
- // If the frame is the placeholder frame, we should only show it if the
- // placeholder has to be visible.
- if (kid->GetContent() != txtCtrl->GetPlaceholderNode() ||
- txtCtrl->GetPlaceholderVisibility()) {
+ // If the frame is the placeholder or preview frame, we should only show
+ // it if it has to be visible.
+ if (!((kid->GetContent() == txtCtrl->GetPlaceholderNode() &&
+ !txtCtrl->GetPlaceholderVisibility()) ||
+ (kid->GetContent() == txtCtrl->GetPreviewNode() &&
+ !txtCtrl->GetPreviewVisibility()))) {
BuildDisplayListForChild(aBuilder, kid, aDirtyRect, set, 0);
}
kid = kid->GetNextSibling();
}
}
mozilla::dom::Element*
nsTextControlFrame::GetPseudoElement(CSSPseudoElementType aType)