diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 1de8831c6d8b..62bb61187994 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -279,19 +279,18 @@ static PRInt32 gReflowInx = -1; //------------------------------------------------------ nsComboboxControlFrame::nsComboboxControlFrame(nsStyleContext* aContext) - : nsBlockFrame(aContext), - mDisplayWidth(0) + : nsBlockFrame(aContext) + , mDisplayFrame(nsnull) + , mButtonFrame(nsnull) + , mDropdownFrame(nsnull) + , mListControlFrame(nsnull) + , mDisplayWidth(0) + , mRecentSelectedIndex(NS_SKIP_NOTIFY_INDEX) + , mDisplayedIndex(-1) + , mDroppedDown(false) + , mInRedisplayText(false) + , mDelayedShowDropDown(false) { - mListControlFrame = nsnull; - mDroppedDown = false; - mDisplayFrame = nsnull; - mButtonFrame = nsnull; - mDropdownFrame = nsnull; - - mInRedisplayText = false; - - mRecentSelectedIndex = NS_SKIP_NOTIFY_INDEX; - REFLOW_COUNTER_INIT() } @@ -325,15 +324,23 @@ nsComboboxControlFrame::CreateAccessible() } #endif -void +void nsComboboxControlFrame::SetFocus(bool aOn, bool aRepaint) { nsWeakFrame weakFrame(this); if (aOn) { nsListControlFrame::ComboboxFocusSet(); mFocused = this; + if (mDelayedShowDropDown) { + ShowDropDown(true); // might destroy us + if (!weakFrame.IsAlive()) { + return; + } + MOZ_ASSERT(!mDelayedShowDropDown); + } } else { mFocused = nsnull; + mDelayedShowDropDown = false; if (mDroppedDown) { mListControlFrame->ComboboxFinish(mDisplayedIndex); // might destroy us if (!weakFrame.IsAlive()) { @@ -794,16 +801,22 @@ nsComboboxControlFrame::GetFrameName(nsAString& aResult) const void nsComboboxControlFrame::ShowDropDown(bool aDoDropDown) { + mDelayedShowDropDown = false; nsEventStates eventStates = mContent->AsElement()->State(); if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) { return; } if (!mDroppedDown && aDoDropDown) { - if (mListControlFrame) { - mListControlFrame->SyncViewWithFrame(); + if (mFocused == this) { + if (mListControlFrame) { + mListControlFrame->SyncViewWithFrame(); + } + ShowList(aDoDropDown); // might destroy us + } else { + // Delay until we get focus, see SetFocus(). + mDelayedShowDropDown = true; } - ShowList(aDoDropDown); // might destroy us } else if (mDroppedDown && !aDoDropDown) { ShowList(aDoDropDown); // might destroy us } diff --git a/layout/forms/nsComboboxControlFrame.h b/layout/forms/nsComboboxControlFrame.h index ff2759fdabd9..660f385b37da 100644 --- a/layout/forms/nsComboboxControlFrame.h +++ b/layout/forms/nsComboboxControlFrame.h @@ -242,9 +242,6 @@ protected: // size to the full width except the drop-marker. nscoord mDisplayWidth; - bool mDroppedDown; // Current state of the dropdown list, true is dropped down - bool mInRedisplayText; - nsRevocableEventPtr mRedisplayTextEvent; PRInt32 mRecentSelectedIndex; @@ -255,6 +252,13 @@ protected: // then open or close the combo box. nsCOMPtr mButtonListener; + // Current state of the dropdown list, true is dropped down. + bool mDroppedDown; + // See comment in HandleRedisplayTextEvent(). + bool mInRedisplayText; + // Acting on ShowDropDown(true) is delayed until we're focused. + bool mDelayedShowDropDown; + // static class data member for Bug 32920 // only one control can be focused at a time static nsComboboxControlFrame * mFocused;