diff --git a/content/html/content/src/nsHTMLOptionElement.cpp b/content/html/content/src/nsHTMLOptionElement.cpp index 40d9f7406d96..795ba6934f2a 100644 --- a/content/html/content/src/nsHTMLOptionElement.cpp +++ b/content/html/content/src/nsHTMLOptionElement.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Pierre Phaneuf + * Mats Palmgren * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -110,18 +111,6 @@ public: NS_IMETHOD SetSelectedInternal(PRBool aValue, PRBool aNotify); // nsIContent - nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, PRBool aNotify) - { - return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify); - } - virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - PRBool aNotify); - virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, - PRBool aNotify); - virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify); - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); virtual PRInt32 IntrinsicState() const; protected: @@ -139,11 +128,6 @@ protected: */ void GetSelect(nsIDOMHTMLSelectElement **aSelectElement) const; - /** - * Notify the frame that the option text or value or label has changed. - */ - void NotifyTextChanged(); - PRPackedBool mIsInitialized; PRPackedBool mIsSelected; }; @@ -407,9 +391,6 @@ nsHTMLOptionElement::SetText(const nsAString& aText) rv = domText->SetData(aText); if (NS_SUCCEEDED(rv)) { - // If we used an existing node, the notification will not happen (the - // notification typically happens in AppendChildTo). - NotifyTextChanged(); usedExistingTextNode = PR_TRUE; } @@ -430,70 +411,6 @@ nsHTMLOptionElement::SetText(const nsAString& aText) return rv; } -void -nsHTMLOptionElement::NotifyTextChanged() -{ - // No need to flush here, if there's no frame yet we don't need to - // force it to be created just to update the selection in it. - nsIFormControlFrame* fcFrame = GetSelectFrame(); - - if (fcFrame) { - nsISelectControlFrame* selectFrame = nsnull; - - CallQueryInterface(fcFrame, &selectFrame); - - if (selectFrame) { - selectFrame->OnOptionTextChanged(this); - } - } -} - -nsresult -nsHTMLOptionElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - PRBool aNotify) -{ - nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, - aValue, aNotify); - if (NS_SUCCEEDED(rv) && aNotify && aName == nsHTMLAtoms::label && - aNameSpaceID == kNameSpaceID_None) { - // XXX Why does this only happen to the combobox? and what about - // when the text gets set and label is blank? - NotifyTextChanged(); - } - - return rv; -} - -// -// Override nsIContent children changing methods so we can detect when our text -// is changing -// -nsresult -nsHTMLOptionElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, - PRBool aNotify) -{ - nsresult rv = nsGenericHTMLElement::InsertChildAt(aKid, aIndex, aNotify); - NotifyTextChanged(); - return rv; -} - -nsresult -nsHTMLOptionElement::AppendChildTo(nsIContent* aKid, PRBool aNotify) -{ - nsresult rv = nsGenericHTMLElement::AppendChildTo(aKid, aNotify); - NotifyTextChanged(); - return rv; -} - -nsresult -nsHTMLOptionElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) -{ - nsresult rv = nsGenericHTMLElement::RemoveChildAt(aIndex, aNotify); - NotifyTextChanged(); - return rv; -} - PRInt32 nsHTMLOptionElement::IntrinsicState() const { diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index afef51ab4b9a..394150c8d31f 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -99,17 +99,13 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); class RedisplayTextEvent : public PLEvent { public: - RedisplayTextEvent(nsComboboxControlFrame* aComboboxControlFrame, - const nsAString& aTextToDisplay); + RedisplayTextEvent(nsComboboxControlFrame* aComboboxControlFrame); void HandleEvent() { NS_STATIC_CAST(nsComboboxControlFrame*, owner) -> - HandleRedisplayTextEvent(mTextToDisplay); + HandleRedisplayTextEvent(); } - -private: - nsString mTextToDisplay; }; PR_STATIC_CALLBACK(void*) @@ -132,9 +128,7 @@ DestroyRedisplayTextPLEvent(PLEvent* aEvent) delete event; } -RedisplayTextEvent::RedisplayTextEvent(nsComboboxControlFrame* aComboboxControlFrame, - const nsAString& aTextToDisplay) - : mTextToDisplay(aTextToDisplay) +RedisplayTextEvent::RedisplayTextEvent(nsComboboxControlFrame* aComboboxControlFrame) { PL_InitEvent(this, aComboboxControlFrame, ::HandleRedisplayTextPLEvent, @@ -453,23 +447,6 @@ nsComboboxControlFrame::Init(nsPresContext* aPresContext, return nsAreaFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); } -// Initialize the text string in the combobox using either the current -// selection in the list box or the first item item in the list box. -void -nsComboboxControlFrame::InitTextStr() -{ - nsAutoString textToDisplay; - PRInt32 selectedIndex; - mListControlFrame->GetSelectedIndex(&selectedIndex); - if (selectedIndex != -1) { - mListControlFrame->GetOptionText(selectedIndex, textToDisplay); - } - - mDisplayedIndex = selectedIndex; - ActuallyDisplayText(textToDisplay, PR_FALSE); -} - - //-------------------------------------------------------------- void nsComboboxControlFrame::InitializeControl(nsPresContext* aPresContext) @@ -1238,6 +1215,17 @@ nsComboboxControlFrame::Reflow(nsPresContext* aPresContext, return nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); } + // Make sure the displayed text is the same as the selected option, bug 297389. + PRInt32 selectedIndex; + nsAutoString selectedOptionText; + mListControlFrame->GetSelectedIndex(&selectedIndex); + if (selectedIndex != -1) { + mListControlFrame->GetOptionText(selectedIndex, selectedOptionText); + } + if (mDisplayedOptionText != selectedOptionText) { + RedisplayText(selectedIndex); + } + // We should cache this instead getting it everytime // the default size of the of scrollbar // that will be the default width of the dropdown button @@ -1783,29 +1771,27 @@ nsresult nsComboboxControlFrame::RedisplayText(PRInt32 aIndex) { // Get the text to display - nsAutoString textToDisplay; if (aIndex != -1) { - mListControlFrame->GetOptionText(aIndex, textToDisplay); + mListControlFrame->GetOptionText(aIndex, mDisplayedOptionText); + } else { + mDisplayedOptionText.Truncate(); } mDisplayedIndex = aIndex; -#ifdef DO_REFLOW_DEBUG - char * str = ToNewCString(textToDisplay); - REFLOW_DEBUG_MSG2("RedisplayText %s\n", str); - delete [] str; -#endif + REFLOW_DEBUG_MSG2("RedisplayText \"%s\"\n", + NS_LossyConvertUCS2toASCII(mDisplayedOptionText).get()); // Send reflow command because the new text maybe larger nsresult rv = NS_OK; if (mDisplayContent && mEventQueueService) { - // Don't call ActuallyDisplayText(aText,PR_TRUE) directly here since that + // Don't call ActuallyDisplayText(PR_TRUE) directly here since that // could cause recursive frame construction. See bug 283117 and the comment in // HandleRedisplayTextEvent() below. nsCOMPtr eventQueue; rv = mEventQueueService->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, getter_AddRefs(eventQueue)); if (eventQueue) { - RedisplayTextEvent* event = new RedisplayTextEvent(this, textToDisplay); + RedisplayTextEvent* event = new RedisplayTextEvent(this); if (event) { // Revoke outstanding events to avoid out-of-order events which could mean // displaying the wrong text. @@ -1830,7 +1816,7 @@ nsComboboxControlFrame::RedisplayText(PRInt32 aIndex) } void -nsComboboxControlFrame::HandleRedisplayTextEvent(const nsAString& aText) +nsComboboxControlFrame::HandleRedisplayTextEvent() { // First, make sure that the content model is up to date and we've // constructed the frames for all our content in the right places. @@ -1848,26 +1834,24 @@ nsComboboxControlFrame::HandleRedisplayTextEvent(const nsAString& aText) mInRedisplayText = PR_TRUE; mRedisplayTextEventPosted = PR_FALSE; - ActuallyDisplayText(aText, PR_TRUE); + ActuallyDisplayText(PR_TRUE); mDisplayFrame->AddStateBits(NS_FRAME_IS_DIRTY); ReflowDirtyChild(GetPresContext()->PresShell(), mDisplayFrame); mInRedisplayText = PR_FALSE; } -nsresult -nsComboboxControlFrame::ActuallyDisplayText(const nsAString& aText, PRBool aNotify) +void +nsComboboxControlFrame::ActuallyDisplayText(PRBool aNotify) { - if (aText.IsEmpty()) { + if (mDisplayedOptionText.IsEmpty()) { // Have to use a non-breaking space for line-height calculations // to be right static const PRUnichar space = 0xA0; mDisplayContent->SetText(&space, 1, aNotify); } else { - mDisplayContent->SetText(aText, aNotify); + mDisplayContent->SetText(mDisplayedOptionText, aNotify); } - - return NS_OK; } NS_IMETHODIMP @@ -2112,7 +2096,9 @@ nsComboboxControlFrame::CreateAnonymousContent(nsPresContext* aPresContext, if (labelContent) { // set the value of the text node mDisplayContent.swap(labelContent); - mDisplayContent->SetText(NS_LITERAL_STRING("X"), PR_TRUE); + mDisplayedIndex = -1; + mDisplayedOptionText.Truncate(); + ActuallyDisplayText(PR_FALSE); nsCOMPtr doc = mContent->GetDocument(); @@ -2286,7 +2272,6 @@ nsComboboxControlFrame::SetInitialChildList(nsPresContext* aPresContext, mPopupFrames.SetFrames(aChildList); } else { rv = nsAreaFrame::SetInitialChildList(aPresContext, aListName, aChildList); - InitTextStr(); for (nsIFrame * child = aChildList; child; child = child->GetNextSibling()) { @@ -2499,22 +2484,6 @@ void nsComboboxControlFrame::FireValueChangeEvent() } } -NS_IMETHODIMP -nsComboboxControlFrame::OnOptionTextChanged(nsIDOMHTMLOptionElement* option) -{ - RedisplaySelectedText(); - if (mDroppedDown) { - nsCOMPtr selectFrame - = do_QueryInterface(mListControlFrame); - if (selectFrame) { - selectFrame->OnOptionTextChanged(option); - } - } - - return NS_OK; -} - - NS_IMETHODIMP nsComboboxControlFrame::OnContentReset() { diff --git a/layout/forms/nsComboboxControlFrame.h b/layout/forms/nsComboboxControlFrame.h index e564311b5067..d1322f5842d3 100644 --- a/layout/forms/nsComboboxControlFrame.h +++ b/layout/forms/nsComboboxControlFrame.h @@ -183,7 +183,6 @@ public: NS_IMETHOD OnOptionSelected(nsPresContext* aPresContext, PRInt32 aIndex, PRBool aSelected); - NS_IMETHOD OnOptionTextChanged(nsIDOMHTMLOptionElement* option); NS_IMETHOD GetDummyFrame(nsIFrame** aFrame); NS_IMETHOD SetDummyFrame(nsIFrame* aFrame); NS_IMETHOD OnSetSelectedIndex(PRInt32 aOldIndex, PRInt32 aNewIndex); @@ -242,12 +241,11 @@ protected: void ShowPopup(PRBool aShowPopup); void ShowList(nsPresContext* aPresContext, PRBool aShowList); void SetChildFrameSize(nsIFrame* aFrame, nscoord aWidth, nscoord aHeight); - void InitTextStr(); void CheckFireOnChange(); void FireValueChangeEvent(); nsresult RedisplayText(PRInt32 aIndex); - void HandleRedisplayTextEvent(const nsAString& aText); - nsresult ActuallyDisplayText(const nsAString& aText, PRBool aNotify); + void HandleRedisplayTextEvent(); + void ActuallyDisplayText(PRBool aNotify); nsresult GetPrimaryComboFrame(nsPresContext* aPresContext, nsIContent* aContent, nsIFrame** aFrame); NS_IMETHOD ToggleList(nsPresContext* aPresContext); @@ -291,6 +289,7 @@ protected: PRInt32 mRecentSelectedIndex; PRInt32 mDisplayedIndex; + nsString mDisplayedOptionText; // make someone to listen to the button. If its programmatically pressed by someone like Accessibility // then open or close the combo box. diff --git a/layout/forms/nsISelectControlFrame.h b/layout/forms/nsISelectControlFrame.h index c122ae0526f7..e231c92062b0 100644 --- a/layout/forms/nsISelectControlFrame.h +++ b/layout/forms/nsISelectControlFrame.h @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Mats Palmgren * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -41,10 +42,10 @@ #include "nsISupports.h" // IID for the nsISelectControlFrame class -#define NS_ISELECTCONTROLFRAME_IID \ -{ 0x62a3bc8e, 0x1312, 0x42f3, \ - { 0x96, 0x7c, 0x37, 0x0f, 0x16, 0x9a, 0xd3, 0xbf } } -// 62a3bc8e-1312-42f3-967c-370f169ad3bf +// 264dc2f5-1cca-47dd-9ebc-699c430be00a +#define NS_ISELECTCONTROLFRAME_IID \ +{ 0x264dc2f5, 0x1cca, 0x47dd, \ + { 0x9e, 0xbc, 0x69, 0x9c, 0x43, 0x0b, 0xe0, 0x0a } } class nsIDOMHTMLOptionElement; @@ -86,13 +87,6 @@ public: PRInt32 aIndex, PRBool aSelected) = 0; - /** - * Notify the frame when an option's text changes - * (We don't pass in the index because it would be expensive for - * the option to figure that out) - */ - NS_IMETHOD OnOptionTextChanged(nsIDOMHTMLOptionElement* option) = 0; - /** * For the content model to tell if there's a dummy frame or not */ diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 9e2d8783fdfc..a0fd12df3348 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Pierre Phaneuf + * Mats Palmgren * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -1727,13 +1728,6 @@ nsListControlFrame::OnOptionSelected(nsPresContext* aPresContext, return NS_OK; } -NS_IMETHODIMP -nsListControlFrame::OnOptionTextChanged(nsIDOMHTMLOptionElement* option) -{ - return NS_OK; -} - - //--------------------------------------------------------- PRIntn nsListControlFrame::GetSkipSides() const diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index ff6f68e6caf0..7c6625fbd02e 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Mats Palmgren * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -182,7 +183,6 @@ public: NS_IMETHOD OnOptionSelected(nsPresContext* aPresContext, PRInt32 aIndex, PRBool aSelected); - NS_IMETHOD OnOptionTextChanged(nsIDOMHTMLOptionElement* option); NS_IMETHOD GetDummyFrame(nsIFrame** aFrame); NS_IMETHOD SetDummyFrame(nsIFrame* aFrame); NS_IMETHOD OnSetSelectedIndex(PRInt32 aOldIndex, PRInt32 aNewIndex);