mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 20:49:27 +00:00
Stop trying to observe content changes for the selected option, instead rely on getting a combobox reflow if it changed. b=297389 r+sr=roc a=asa
This commit is contained in:
parent
83e97bb062
commit
293246508e
@ -21,6 +21,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
*
|
||||
* 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
|
||||
{
|
||||
|
@ -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<nsIEventQueue> 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<nsIDocument> 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<nsISelectControlFrame> selectFrame
|
||||
= do_QueryInterface(mListControlFrame);
|
||||
if (selectFrame) {
|
||||
selectFrame->OnOptionTextChanged(option);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsComboboxControlFrame::OnContentReset()
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -20,6 +20,7 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
@ -21,6 +21,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
*
|
||||
* 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
|
||||
|
@ -20,6 +20,7 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
*
|
||||
* 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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user