diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index ce76f428e55..9030326ce31 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -1939,6 +1939,13 @@ nsComboboxControlFrame::SelectionChanged() return rv; } +NS_IMETHODIMP +nsComboboxControlFrame::GetIndexOfDisplayArea(PRInt32* aSelectedIndex) +{ + NS_ENSURE_ARG_POINTER(aSelectedIndex); + *aSelectedIndex = mSelectedIndex; + return NS_OK; +} //---------------------------------------------------------------------- // nsISelectControlFrame diff --git a/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index 4584222a836..86607ea0544 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -166,6 +166,7 @@ public: NS_IMETHOD UpdateSelection(PRBool aDoDispatchEvent, PRBool aForceUpdate, PRInt32 aNewIndex); NS_IMETHOD AbsolutelyPositionDropDown(); NS_IMETHOD GetAbsoluteRect(nsRect* aRect); + NS_IMETHOD GetIndexOfDisplayArea(PRInt32* aSelectedIndex); // nsISelectControlFrame NS_IMETHOD AddOption(nsIPresContext* aPresContext, PRInt32 index); diff --git a/mozilla/layout/forms/nsIComboboxControlFrame.h b/mozilla/layout/forms/nsIComboboxControlFrame.h index 38dd1cb024c..81ac099086e 100644 --- a/mozilla/layout/forms/nsIComboboxControlFrame.h +++ b/mozilla/layout/forms/nsIComboboxControlFrame.h @@ -115,6 +115,23 @@ public: */ NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) = 0; + /** + * This returns the index of the item that is currently being displayed + * in the display area. It may differ from what the currently Selected index + * is in in the dropdown. + * + * Detailed explanation: + * When the dropdown is dropped down via a mouse click and the user moves the mouse + * up and down without clicking, the currently selected item is being tracking inside + * the dropdown, but the combobox is not being updated. When the user selects items + * with the arrow keys, the combobox is being updated. So when the user clicks outside + * the dropdown and it needs to roll up it has to decide whether to keep the current + * selection or not. This method is used to get the current index in the combobox to + * compare it to the current index in the dropdown to see if the combox has been updated + * and that way it knows whether to "cancel" the the current selection residing in the + * dropdown. Or whether to leave the selection alone. + */ + NS_IMETHOD GetIndexOfDisplayArea(PRInt32* aSelectedIndex) = 0; }; #endif diff --git a/mozilla/layout/forms/nsListControlFrame.cpp b/mozilla/layout/forms/nsListControlFrame.cpp index 2f0f6aea3ba..0f9b93694a5 100644 --- a/mozilla/layout/forms/nsListControlFrame.cpp +++ b/mozilla/layout/forms/nsListControlFrame.cpp @@ -2847,10 +2847,30 @@ nsListControlFrame::AboutToDropDown() NS_IMETHODIMP nsListControlFrame::AboutToRollup() { - // XXX By uncommenting this line below the "act" of rolling up - // will reset the the contents of the combobox to it's original contents - // (i.e. the contents before it was dropped down - ResetSelectedItem(); + // XXX To have clicking outside the combobox ALWAYS reset the contents to the + // state before it was dropped, remove the all the code in the "if" below and replace it + // with just the call to ResetSelectedItem() + // + // + // When the dropdown is dropped down via a mouse click and the user moves the mouse + // up and down without clicking, the currently selected item is being tracking inside + // the dropdown, but the combobox is not being updated. When the user selects items + // with the arrow keys, the combobox is being updated. So when the user clicks outside + // the dropdown and it needs to roll up it has to decide whether to keep the current + // selection or not. The GetIndexOfDisplayArea method is used to get the current index + // in the combobox to compare it to the current index in the dropdown to see if the combox + // has been updated and that way it knows whether to "cancel" the the current selection + // residing in the dropdown. Or whether to leave the selection alone. + if (IsInDropDownMode() == PR_TRUE) { + PRInt32 index; + mComboboxFrame->GetIndexOfDisplayArea(&index); + // if the indexes do NOT match then the selection in the combobox + // was never updated, and therefore we should reset the the selection back to + // whatever it was before it was dropped down. + if (index != mSelectedIndex) { + ResetSelectedItem(); + } + } return NS_OK; } diff --git a/mozilla/layout/html/forms/public/nsIComboboxControlFrame.h b/mozilla/layout/html/forms/public/nsIComboboxControlFrame.h index 38dd1cb024c..81ac099086e 100644 --- a/mozilla/layout/html/forms/public/nsIComboboxControlFrame.h +++ b/mozilla/layout/html/forms/public/nsIComboboxControlFrame.h @@ -115,6 +115,23 @@ public: */ NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) = 0; + /** + * This returns the index of the item that is currently being displayed + * in the display area. It may differ from what the currently Selected index + * is in in the dropdown. + * + * Detailed explanation: + * When the dropdown is dropped down via a mouse click and the user moves the mouse + * up and down without clicking, the currently selected item is being tracking inside + * the dropdown, but the combobox is not being updated. When the user selects items + * with the arrow keys, the combobox is being updated. So when the user clicks outside + * the dropdown and it needs to roll up it has to decide whether to keep the current + * selection or not. This method is used to get the current index in the combobox to + * compare it to the current index in the dropdown to see if the combox has been updated + * and that way it knows whether to "cancel" the the current selection residing in the + * dropdown. Or whether to leave the selection alone. + */ + NS_IMETHOD GetIndexOfDisplayArea(PRInt32* aSelectedIndex) = 0; }; #endif diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index ce76f428e55..9030326ce31 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -1939,6 +1939,13 @@ nsComboboxControlFrame::SelectionChanged() return rv; } +NS_IMETHODIMP +nsComboboxControlFrame::GetIndexOfDisplayArea(PRInt32* aSelectedIndex) +{ + NS_ENSURE_ARG_POINTER(aSelectedIndex); + *aSelectedIndex = mSelectedIndex; + return NS_OK; +} //---------------------------------------------------------------------- // nsISelectControlFrame diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h index 4584222a836..86607ea0544 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h @@ -166,6 +166,7 @@ public: NS_IMETHOD UpdateSelection(PRBool aDoDispatchEvent, PRBool aForceUpdate, PRInt32 aNewIndex); NS_IMETHOD AbsolutelyPositionDropDown(); NS_IMETHOD GetAbsoluteRect(nsRect* aRect); + NS_IMETHOD GetIndexOfDisplayArea(PRInt32* aSelectedIndex); // nsISelectControlFrame NS_IMETHOD AddOption(nsIPresContext* aPresContext, PRInt32 index); diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp index 2f0f6aea3ba..0f9b93694a5 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp @@ -2847,10 +2847,30 @@ nsListControlFrame::AboutToDropDown() NS_IMETHODIMP nsListControlFrame::AboutToRollup() { - // XXX By uncommenting this line below the "act" of rolling up - // will reset the the contents of the combobox to it's original contents - // (i.e. the contents before it was dropped down - ResetSelectedItem(); + // XXX To have clicking outside the combobox ALWAYS reset the contents to the + // state before it was dropped, remove the all the code in the "if" below and replace it + // with just the call to ResetSelectedItem() + // + // + // When the dropdown is dropped down via a mouse click and the user moves the mouse + // up and down without clicking, the currently selected item is being tracking inside + // the dropdown, but the combobox is not being updated. When the user selects items + // with the arrow keys, the combobox is being updated. So when the user clicks outside + // the dropdown and it needs to roll up it has to decide whether to keep the current + // selection or not. The GetIndexOfDisplayArea method is used to get the current index + // in the combobox to compare it to the current index in the dropdown to see if the combox + // has been updated and that way it knows whether to "cancel" the the current selection + // residing in the dropdown. Or whether to leave the selection alone. + if (IsInDropDownMode() == PR_TRUE) { + PRInt32 index; + mComboboxFrame->GetIndexOfDisplayArea(&index); + // if the indexes do NOT match then the selection in the combobox + // was never updated, and therefore we should reset the the selection back to + // whatever it was before it was dropped down. + if (index != mSelectedIndex) { + ResetSelectedItem(); + } + } return NS_OK; }