From 2ab9b3a14d929309e8ff40cb46a8f796f44f3b9d Mon Sep 17 00:00:00 2001 From: "rods%netscape.com" Date: Wed, 20 Dec 2000 15:15:28 +0000 Subject: [PATCH] 53259 - min-width and max-width not supported on form control 53457 - multiple items can be selected in select size=1 or in single select listbox 50376 - Cannot select with DOM option on dynamically created SELECT element 62442 - Incorrect extended selection behavior in listboxes First big change is getting rid of local variables for border and padding and use the ones in the reflow state Changed "IsInDropDownMode() == PR_TRUE && mComboboxFrame" to "IsInDropDownMode() == PR_TRUE" Fix for regression from changing of how key events work (no bug assigned), this fix enabled the user to hit 'f' or 'F' and get to the first item that start with 'f' or 'F' r=kmcclusk sr=buster --- layout/forms/nsListControlFrame.cpp | 315 +++++++++++++++---- layout/forms/nsListControlFrame.h | 12 + layout/html/forms/src/nsListControlFrame.cpp | 315 +++++++++++++++---- layout/html/forms/src/nsListControlFrame.h | 12 + 4 files changed, 522 insertions(+), 132 deletions(-) diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index b4fc25de1172..2f0f6aea3ba0 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -616,29 +616,16 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, nscoord scrollbarWidth = NSToCoordRound(sbWidth); //nscoord scrollbarHeight = NSToCoordRound(sbHeight); - // Subtract out the borders - nsMargin border; - if (!aReflowState.mStyleSpacing->GetBorder(border)) { - NS_NOTYETIMPLEMENTED("percentage border"); - border.SizeTo(0, 0, 0, 0); - } - - nsMargin padding; - if (!aReflowState.mStyleSpacing->GetPadding(padding)) { - NS_NOTYETIMPLEMENTED("percentage padding"); - padding.SizeTo(0, 0, 0, 0); - } - - mMaxWidth -= (border.left + border.right + padding.left + padding.right); - mMaxHeight -= (border.top + border.bottom + padding.top + padding.bottom); + mMaxWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + mMaxHeight -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; // Now the scrolledAreaWidth and scrolledAreaHeight are exactly // wide and high enough to enclose their contents PRBool isInDropDownMode = IsInDropDownMode(); - scrolledAreaWidth -= (border.left + border.right + padding.left + padding.right); - scrolledAreaHeight -= (border.top + border.bottom + padding.top + padding.bottom); + scrolledAreaWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + scrolledAreaHeight -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; nscoord visibleWidth = 0; if (isInDropDownMode) { @@ -646,16 +633,13 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, visibleWidth = scrolledAreaWidth; } else { visibleWidth = aReflowState.mComputedWidth; - visibleWidth -= (border.left + border.right + padding.left + padding.right); - //scrolledAreaHeight -= (border.top + border.bottom + padding.top + padding.bottom); + visibleWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; } } else { if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { visibleWidth = scrolledAreaWidth; } else { visibleWidth = aReflowState.mComputedWidth;// - scrollbarWidth; - // XXX rods - this hould not be subtracted in - //visibleWidth -= (border.left + border.right + padding.left + padding.right); } } @@ -671,7 +655,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, // of option elements. The reason is that their may be option groups in addition to // option elements. Either of which may be visible or invisible. PRInt32 heightOfARow = scrolledAreaDesiredSize.maxElementSize->height; - heightOfARow -= (border.top + border.bottom + padding.top + padding.bottom); + heightOfARow -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; // Check to see if we have zero items PRInt32 length = 0; @@ -741,9 +725,9 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, nscoord screenHeight = NSIntPixelsToTwips(screenHeightInPixels, p2t); nscoord availDropHgt = (screenHeight / 2) - (heightOfARow*2); // approx half screen minus combo size - availDropHgt -= (border.top + border.bottom + padding.top + padding.bottom); + availDropHgt -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - nscoord hgt = visibleHeight + border.top + border.bottom + padding.top + padding.bottom; + nscoord hgt = visibleHeight + aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; if (heightOfARow > 0) { if (hgt > availDropHgt) { visibleHeight = (availDropHgt / heightOfARow) * heightOfARow; @@ -762,7 +746,6 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, // Calculate the visible height of the listbox if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { visibleHeight = aReflowState.mComputedHeight; - visibleHeight -= (border.top + border.bottom + padding.top + padding.bottom); } else { mNumDisplayRows = 1; GetSizeAttribute(&mNumDisplayRows); @@ -816,7 +799,29 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, } if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth += (border.left + border.right + padding.left + padding.right); + visibleWidth += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + } + + // When in dropdown mode make sure we obey min/max-width and min/max-height + if (!isInDropDownMode) { + nscoord fullWidth = visibleWidth + aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + if (fullWidth > aReflowState.mComputedMaxWidth) { + visibleWidth = aReflowState.mComputedMaxWidth - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right; + } + if (fullWidth < aReflowState.mComputedMinWidth) { + visibleWidth = aReflowState.mComputedMinWidth - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right; + } + + // calculate full height for comparison + // must add in Border & Padding twice because the scrolled area also inherits Border & Padding + nscoord fullHeight = visibleHeight + aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; + // + aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; + if (fullHeight > aReflowState.mComputedMaxHeight) { + visibleHeight = aReflowState.mComputedMaxHeight - aReflowState.mComputedBorderPadding.top - aReflowState.mComputedBorderPadding.bottom; + } + if (fullHeight < aReflowState.mComputedMinHeight) { + visibleHeight = aReflowState.mComputedMinHeight - aReflowState.mComputedBorderPadding.top - aReflowState.mComputedBorderPadding.bottom; + } } // Do a second reflow with the adjusted width and height settings @@ -853,11 +858,11 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, #endif if (aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.width = aDesiredSize.width - (border.left + border.right + padding.left + padding.right); + mCachedAvailableSize.width = aDesiredSize.width - (aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right); REFLOW_DEBUG_MSG2("** nsLCF Caching AW: %d\n", PX(mCachedAvailableSize.width)); } if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.height = aDesiredSize.height - (border.top + border.bottom + padding.top + padding.bottom); + mCachedAvailableSize.height = aDesiredSize.height - (aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom); REFLOW_DEBUG_MSG2("** nsLCF Caching AH: %d\n", PX(mCachedAvailableSize.height)); } @@ -1152,8 +1157,17 @@ nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) // Shift is held down SetContentSelected(mSelectedIndex, PR_TRUE); if (mEndExtendedIndex == kNothingSelected) { - mEndExtendedIndex = mSelectedIndex; - ExtendedSelection(mStartExtendedIndex, mEndExtendedIndex, PR_FALSE, PR_TRUE); + if (mOldSelectedIndex == kNothingSelected) { + mStartExtendedIndex = mSelectedIndex; + mEndExtendedIndex = kNothingSelected; + } else { + if (mSelectedIndex == mOldSelectedIndex) { + mEndExtendedIndex = kNothingSelected; + } else { + mEndExtendedIndex = mSelectedIndex; + } + ExtendedSelection(mStartExtendedIndex, mEndExtendedIndex, PR_FALSE, PR_TRUE); + } } else { if (mStartExtendedIndex < mEndExtendedIndex) { if (mSelectedIndex < mStartExtendedIndex) { @@ -1164,7 +1178,11 @@ nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) mEndExtendedIndex = mSelectedIndex; } else if (mSelectedIndex < mEndExtendedIndex) { ExtendedSelection(mSelectedIndex+1, mEndExtendedIndex, PR_FALSE, PR_FALSE); - mEndExtendedIndex = mSelectedIndex; + if (mSelectedIndex == mStartExtendedIndex) { + mEndExtendedIndex = kNothingSelected; + } else { + mEndExtendedIndex = mSelectedIndex; + } } } else if (mStartExtendedIndex > mEndExtendedIndex) { if (mSelectedIndex > mStartExtendedIndex) { @@ -1175,7 +1193,11 @@ nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) mEndExtendedIndex = mSelectedIndex; } else if (mSelectedIndex > mEndExtendedIndex) { ExtendedSelection(mEndExtendedIndex, mSelectedIndex-1, PR_FALSE, PR_FALSE); - mEndExtendedIndex = mSelectedIndex; + if (mSelectedIndex == mStartExtendedIndex) { + mEndExtendedIndex = kNothingSelected; + } else { + mEndExtendedIndex = mSelectedIndex; + } } } } @@ -1195,7 +1217,12 @@ nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) ClearSelection(); } } - +#ifdef DEBUG_rods + printf("mSelectedIndex: %d\n", mSelectedIndex); + printf("mOldSelectedIndex: %d\n", mOldSelectedIndex); + printf("mStartExtendedIndex: %d\n", mStartExtendedIndex); + printf("mEndExtendedIndex: %d\n", mEndExtendedIndex); +#endif } //--------------------------------------------------------- @@ -1716,19 +1743,21 @@ nsListControlFrame::SetContentSelected(PRInt32 aIndex, PRBool aSelected) if (content != nsnull) { nsCOMPtr presShell; mPresContext->GetShell(getter_AddRefs(presShell)); - nsIFrame * childframe; - nsresult result = presShell->GetPrimaryFrameFor(content, &childframe); - if (NS_SUCCEEDED(result) && childframe != nsnull) { - if (aSelected) { - DisplaySelected(content); - // Now that it is selected scroll to it - ScrollToFrame(content); + if (presShell) { + nsIFrame * childframe; + nsresult result = presShell->GetPrimaryFrameFor(content, &childframe); + if (NS_SUCCEEDED(result) && childframe != nsnull) { + if (aSelected) { + DisplaySelected(content); + // Now that it is selected scroll to it + ScrollToFrame(content); + } else { + DisplayDeselected(content); + } } else { - DisplayDeselected(content); + mDelayedIndexSetting = aIndex; + mDelayedValueSetting = aSelected; } - } else { - mDelayedIndexSetting = aIndex; - mDelayedValueSetting = aSelected; } NS_RELEASE(content); } @@ -1867,13 +1896,21 @@ nsListControlFrame::Reset(nsIPresContext* aPresContext) mSelectionCacheLength++; if (selected) { - mSelectedIndex = i; - SetContentSelected(i, PR_TRUE); - if (multiple) { - mStartExtendedIndex = i; - if (mEndExtendedIndex == kNothingSelected) { - mEndExtendedIndex = i; + if (mSelectedIndex == kNothingSelected || + (mSelectedIndex != kNothingSelected && multiple)) { + mSelectedIndex = i; + SetContentSelected(i, PR_TRUE); + if (multiple) { + mStartExtendedIndex = i; + if (mEndExtendedIndex == kNothingSelected) { + mEndExtendedIndex = i; + } } + } else { + SetContentSelected(mSelectedIndex, PR_FALSE); + mSelectionCache->ReplaceElementAt((void*)PR_FALSE, mSelectedIndex); + mSelectedIndex = i; + SetContentSelected(i, PR_TRUE); } } } @@ -2330,6 +2367,119 @@ nsListControlFrame::RemoveOption(nsIPresContext* aPresContext, PRInt32 aIndex) return NS_OK; } +#ifdef FIX_FOR_BUG_50376 +//------------------------------------------------------------------- +nsresult nsListControlFrame::GetPresStateAndValueArray(nsISupportsArray ** aSuppArray) +{ + // Basically we need to check for and/or create + // both the PresState and the Supports Array + // There may already be a no PresState and no Supports Array + // or there may be PresState and no Supports Array + // or there may be both + + // So assume we need to create the supports array and + //flip it off if we don't + PRBool createSupportsArray = PR_TRUE; + + nsresult res = NS_ERROR_FAILURE; + if (mPresState) { + nsCOMPtr supp; + mPresState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("selecteditems"), getter_AddRefs(supp)); + if (supp) { + res = supp->QueryInterface(NS_GET_IID(nsISupportsArray), (void**)aSuppArray); + if (NS_FAILED(res)) { + return res; + } + createSupportsArray = PR_FALSE; + } + } else { + NS_NewPresState(getter_AddRefs(mPresState)); + } + + if (createSupportsArray) { + res = NS_NewISupportsArray(aSuppArray); + if (NS_SUCCEEDED(res)) { + res = mPresState->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("selecteditems"), *aSuppArray); + } + } + return res; +} + +//------------------------------------------------------------------- +nsresult nsListControlFrame::SetSelectionInPresState(PRInt32 aIndex, PRBool aValue) +{ + // if there is no PresState and we ned to remove it + // from the PresState, then there is nothing to do + if (!mPresState && !aValue) { + return NS_OK; + } + + nsCOMPtr suppArray; + nsresult res = GetPresStateAndValueArray(getter_AddRefs(suppArray)); + + if (NS_FAILED(res) || !suppArray) + return res; + + if (aValue) { + PRUint32 count; + suppArray->Count(&count); + return SetOptionIntoPresState(suppArray, aIndex, count); + } else { + return RemoveOptionFromPresState(suppArray, aIndex); + } + +} + +//------------------------------------------------------------------- +nsresult nsListControlFrame::RemoveOptionFromPresState(nsISupportsArray * aSuppArray, + PRInt32 aIndex) +{ + NS_ENSURE_ARG_POINTER(aSuppArray); + nsresult res = NS_ERROR_FAILURE; + PRUint32 count; + aSuppArray->Count(&count); + nsCOMPtr thisVal; + for (PRUint32 i=0; i suppval = getter_AddRefs(aSuppArray->ElementAt(i)); + thisVal = do_QueryInterface(suppval); + if (thisVal) { + PRInt32 optIndex; + res = thisVal->GetData(&optIndex); + if (NS_SUCCEEDED(res)) { + if (optIndex == aIndex) { + aSuppArray->RemoveElementAt(i); + return NS_OK; + } + } + } else { + res = NS_ERROR_UNEXPECTED; + } + if (NS_FAILED(res)) break; + } + return res; +} + +//------------------------------------------------------------------- +nsresult nsListControlFrame::SetOptionIntoPresState(nsISupportsArray * aSuppArray, + PRInt32 aIndex, + PRInt32 anItemNum) +{ + NS_ENSURE_ARG_POINTER(aSuppArray); + nsCOMPtr thisVal; + nsresult res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, + nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(thisVal)); + if (NS_SUCCEEDED(res) && thisVal) { + res = thisVal->SetData(aIndex); + if (NS_SUCCEEDED(res)) { + PRBool okay = aSuppArray->InsertElementAt((nsISupports *)thisVal, anItemNum); + if (!okay) res = NS_ERROR_OUT_OF_MEMORY; // Most likely cause; + } + } + return res; +} + +#endif // FIX_FOR_BUG_50376 + //--------------------------------------------------------- // Select the specified item in the listbox using control logic. // If it a single selection listbox the previous selection will be @@ -2337,6 +2487,12 @@ nsListControlFrame::RemoveOption(nsIPresContext* aPresContext, PRInt32 aIndex) NS_IMETHODIMP nsListControlFrame::SetOptionSelected(PRInt32 aIndex, PRBool aValue) { +#ifdef FIX_FOR_BUG_50376 + if (!mIsAllFramesHere && !mHasBeenInitialized) { + return SetSelectionInPresState(aIndex, aValue); + } +#endif // FIX_FOR_BUG_50376 + PRBool multiple; nsresult rv = GetMultiple(&multiple); if (NS_SUCCEEDED(rv)) { @@ -2688,10 +2844,12 @@ nsListControlFrame::AboutToDropDown() //--------------------------------------------------------- // We are about to be rolledup from the outside (ComboboxFrame) -// this is a "cancelled" action not a selected action 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(); return NS_OK; } @@ -2824,6 +2982,9 @@ void nsListControlFrame::ResetSelectedItem() { if (mIsAllFramesHere) { ToggleSelected(mSelectedIndexWhenPoppedDown); + if (IsInDropDownMode() == PR_TRUE) { + mComboboxFrame->ListWasSelected(mPresContext, PR_TRUE); + } } } @@ -2862,7 +3023,7 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent) // if a right button click is on the combobox itself // or on the select when in listbox mode, then let the click through if (!IsLeftButton(aMouseEvent)) { - if (IsInDropDownMode()) { + if (IsInDropDownMode() == PR_TRUE) { if (!IsClickingInCombobox(aMouseEvent)) { aMouseEvent->PreventDefault(); aMouseEvent->PreventCapture(); @@ -2887,14 +3048,15 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent) PRBool optionIsDisabled; if (NS_OK == IsTargetOptionDisabled(optionIsDisabled)) { if (optionIsDisabled) { - if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) { + if (IsInDropDownMode() == PR_TRUE) { ResetSelectedItem(); - mComboboxFrame->ListWasSelected(mPresContext, PR_FALSE); - } + } else { + SetContentSelected(mSelectedIndex, PR_FALSE); + mSelectedIndex = kNothingSelected; + } REFLOW_DEBUG_MSG(">>>>>> Option is disabled"); mButtonDown = PR_FALSE; CaptureMouseEvents(mPresContext, PR_FALSE); - SetContentSelected(mSelectedIndex, PR_FALSE); return NS_OK; } } @@ -3165,7 +3327,7 @@ nsListControlFrame::MouseMove(nsIDOMEvent* aMouseEvent) NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null."); //REFLOW_DEBUG_MSG("MouseMove\n"); - if (mComboboxFrame) { // Synonym for IsInDropDownMode() + if (IsInDropDownMode() == PR_TRUE) { PRBool isDroppedDown = PR_FALSE; mComboboxFrame->IsDroppedDown(&isDroppedDown); if (isDroppedDown) { @@ -3198,7 +3360,7 @@ nsListControlFrame::DragMove(nsIDOMEvent* aMouseEvent) NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null."); //REFLOW_DEBUG_MSG("DragMove\n"); - if (!mComboboxFrame) { // Synonym for IsInDropDownMode() + if (IsInDropDownMode() == PR_FALSE) { // check to make sure we are a mulitple select list PRBool multipleSelections = PR_FALSE; GetMultiple(&multipleSelections); @@ -3477,9 +3639,26 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) PRBool isAlt = PR_FALSE; PRBool isMeta = PR_FALSE; keyEvent->GetCtrlKey(&isControl); - keyEvent->GetAltKey(&isAlt); keyEvent->GetMetaKey(&isMeta); - if (isControl || isAlt || isMeta) { + if (isControl || isMeta) { + return NS_OK; + } + + keyEvent->GetAltKey(&isAlt); + // Fix for Bug 62425 + if (isAlt) { +#ifdef FIX_FOR_BUG_62425 + if (code == nsIDOMKeyEvent::DOM_VK_UP || code == nsIDOMKeyEvent::DOM_VK_DOWN) { + if (IsInDropDownMode() == PR_TRUE) { + PRBool isDroppedDown; + mComboboxFrame->IsDroppedDown(&isDroppedDown); + mComboboxFrame->ShowDropDown(!isDroppedDown); + aKeyEvent->PreventDefault(); + aKeyEvent->PreventCapture(); + aKeyEvent->PreventBubble(); + } + } +#endif return NS_OK; } @@ -3543,9 +3722,9 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) case nsIDOMKeyEvent::DOM_VK_RETURN: { if (mComboboxFrame != nsnull) { - PRBool isDroppedDown; - mComboboxFrame->IsDroppedDown(&isDroppedDown); - if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) { + if (IsInDropDownMode() == PR_TRUE) { + PRBool isDroppedDown; + mComboboxFrame->IsDroppedDown(&isDroppedDown); mComboboxFrame->ListWasSelected(mPresContext, isDroppedDown); } else { UpdateSelection(PR_TRUE, PR_FALSE, mContent); @@ -3554,9 +3733,8 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) } break; case nsIDOMKeyEvent::DOM_VK_ESCAPE: { - if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) { + if (IsInDropDownMode() == PR_TRUE) { ResetSelectedItem(); - mComboboxFrame->ListWasSelected(mPresContext, PR_FALSE); } } break; @@ -3600,6 +3778,7 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) default: { // Select option with this as the first character // XXX Not I18N compliant + code = (PRUint32)nsCRT::ToLower((PRUnichar)code); PRInt32 selectedIndex = (mSelectedIndex == kNothingSelected ? 0 : mSelectedIndex+1) % numOptions; PRInt32 startedAtIndex = selectedIndex; PRBool loopedAround = PR_FALSE; @@ -3665,7 +3844,7 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) // XXX - Are we cover up a problem here??? // Why aren't they getting flushed each time? // because this isn't needed for Gfx - if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) { + if (IsInDropDownMode() == PR_TRUE) { nsCOMPtr presShell; mPresContext->GetShell(getter_AddRefs(presShell)); presShell->FlushPendingNotifications(); @@ -3704,6 +3883,9 @@ nsListControlFrame::SaveStateInternal(nsIPresContext* aPresContext, nsIPresState PRBool selected = PR_FALSE; res = GetOptionSelected(i, &selected); if (NS_SUCCEEDED(res) && selected) { +#ifdef FIX_FOR_BUG_50376 + res = SetOptionIntoPresState(value, i, j++); +#else nsCOMPtr thisVal; res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(thisVal)); @@ -3714,6 +3896,7 @@ nsListControlFrame::SaveStateInternal(nsIPresContext* aPresContext, nsIPresState if (!okay) res = NS_ERROR_OUT_OF_MEMORY; // Most likely cause; } } +#endif } if (!NS_SUCCEEDED(res)) break; } diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index ba6a026f87f3..b1c1ebc17328 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -152,6 +152,8 @@ protected: /** * Frame-based listbox. */ +#define FIX_FOR_BUG_50376 + class nsListControlFrame : public nsScrollFrame, public nsIFormControlFrame, @@ -293,6 +295,16 @@ protected: void AdjustIndexForDisabledOpt(PRInt32 &anNewIndex, PRInt32 &anOldIndex, PRBool &aDoSetNewIndex, PRBool &aWasDisabled, PRInt32 aNumOptions, PRInt32 aDoAdjustInc, PRInt32 aDoAdjustIncNext); +#ifdef FIX_FOR_BUG_50376 + // PresState Helper Methods + nsresult GetPresStateAndValueArray(nsISupportsArray ** aSuppArray); + nsresult SetOptionIntoPresState(nsISupportsArray * aSuppArray, + PRInt32 aIndex, + PRInt32 anItemNum); + nsresult SetSelectionInPresState(PRInt32 aIndex, PRBool aValue); + nsresult RemoveOptionFromPresState(nsISupportsArray * aSuppArray, + PRInt32 aIndex); +#endif nsListControlFrame(); virtual ~nsListControlFrame(); diff --git a/layout/html/forms/src/nsListControlFrame.cpp b/layout/html/forms/src/nsListControlFrame.cpp index b4fc25de1172..2f0f6aea3ba0 100644 --- a/layout/html/forms/src/nsListControlFrame.cpp +++ b/layout/html/forms/src/nsListControlFrame.cpp @@ -616,29 +616,16 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, nscoord scrollbarWidth = NSToCoordRound(sbWidth); //nscoord scrollbarHeight = NSToCoordRound(sbHeight); - // Subtract out the borders - nsMargin border; - if (!aReflowState.mStyleSpacing->GetBorder(border)) { - NS_NOTYETIMPLEMENTED("percentage border"); - border.SizeTo(0, 0, 0, 0); - } - - nsMargin padding; - if (!aReflowState.mStyleSpacing->GetPadding(padding)) { - NS_NOTYETIMPLEMENTED("percentage padding"); - padding.SizeTo(0, 0, 0, 0); - } - - mMaxWidth -= (border.left + border.right + padding.left + padding.right); - mMaxHeight -= (border.top + border.bottom + padding.top + padding.bottom); + mMaxWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + mMaxHeight -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; // Now the scrolledAreaWidth and scrolledAreaHeight are exactly // wide and high enough to enclose their contents PRBool isInDropDownMode = IsInDropDownMode(); - scrolledAreaWidth -= (border.left + border.right + padding.left + padding.right); - scrolledAreaHeight -= (border.top + border.bottom + padding.top + padding.bottom); + scrolledAreaWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + scrolledAreaHeight -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; nscoord visibleWidth = 0; if (isInDropDownMode) { @@ -646,16 +633,13 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, visibleWidth = scrolledAreaWidth; } else { visibleWidth = aReflowState.mComputedWidth; - visibleWidth -= (border.left + border.right + padding.left + padding.right); - //scrolledAreaHeight -= (border.top + border.bottom + padding.top + padding.bottom); + visibleWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; } } else { if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { visibleWidth = scrolledAreaWidth; } else { visibleWidth = aReflowState.mComputedWidth;// - scrollbarWidth; - // XXX rods - this hould not be subtracted in - //visibleWidth -= (border.left + border.right + padding.left + padding.right); } } @@ -671,7 +655,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, // of option elements. The reason is that their may be option groups in addition to // option elements. Either of which may be visible or invisible. PRInt32 heightOfARow = scrolledAreaDesiredSize.maxElementSize->height; - heightOfARow -= (border.top + border.bottom + padding.top + padding.bottom); + heightOfARow -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; // Check to see if we have zero items PRInt32 length = 0; @@ -741,9 +725,9 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, nscoord screenHeight = NSIntPixelsToTwips(screenHeightInPixels, p2t); nscoord availDropHgt = (screenHeight / 2) - (heightOfARow*2); // approx half screen minus combo size - availDropHgt -= (border.top + border.bottom + padding.top + padding.bottom); + availDropHgt -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - nscoord hgt = visibleHeight + border.top + border.bottom + padding.top + padding.bottom; + nscoord hgt = visibleHeight + aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; if (heightOfARow > 0) { if (hgt > availDropHgt) { visibleHeight = (availDropHgt / heightOfARow) * heightOfARow; @@ -762,7 +746,6 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, // Calculate the visible height of the listbox if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { visibleHeight = aReflowState.mComputedHeight; - visibleHeight -= (border.top + border.bottom + padding.top + padding.bottom); } else { mNumDisplayRows = 1; GetSizeAttribute(&mNumDisplayRows); @@ -816,7 +799,29 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, } if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth += (border.left + border.right + padding.left + padding.right); + visibleWidth += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + } + + // When in dropdown mode make sure we obey min/max-width and min/max-height + if (!isInDropDownMode) { + nscoord fullWidth = visibleWidth + aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + if (fullWidth > aReflowState.mComputedMaxWidth) { + visibleWidth = aReflowState.mComputedMaxWidth - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right; + } + if (fullWidth < aReflowState.mComputedMinWidth) { + visibleWidth = aReflowState.mComputedMinWidth - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right; + } + + // calculate full height for comparison + // must add in Border & Padding twice because the scrolled area also inherits Border & Padding + nscoord fullHeight = visibleHeight + aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; + // + aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; + if (fullHeight > aReflowState.mComputedMaxHeight) { + visibleHeight = aReflowState.mComputedMaxHeight - aReflowState.mComputedBorderPadding.top - aReflowState.mComputedBorderPadding.bottom; + } + if (fullHeight < aReflowState.mComputedMinHeight) { + visibleHeight = aReflowState.mComputedMinHeight - aReflowState.mComputedBorderPadding.top - aReflowState.mComputedBorderPadding.bottom; + } } // Do a second reflow with the adjusted width and height settings @@ -853,11 +858,11 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, #endif if (aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.width = aDesiredSize.width - (border.left + border.right + padding.left + padding.right); + mCachedAvailableSize.width = aDesiredSize.width - (aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right); REFLOW_DEBUG_MSG2("** nsLCF Caching AW: %d\n", PX(mCachedAvailableSize.width)); } if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { - mCachedAvailableSize.height = aDesiredSize.height - (border.top + border.bottom + padding.top + padding.bottom); + mCachedAvailableSize.height = aDesiredSize.height - (aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom); REFLOW_DEBUG_MSG2("** nsLCF Caching AH: %d\n", PX(mCachedAvailableSize.height)); } @@ -1152,8 +1157,17 @@ nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) // Shift is held down SetContentSelected(mSelectedIndex, PR_TRUE); if (mEndExtendedIndex == kNothingSelected) { - mEndExtendedIndex = mSelectedIndex; - ExtendedSelection(mStartExtendedIndex, mEndExtendedIndex, PR_FALSE, PR_TRUE); + if (mOldSelectedIndex == kNothingSelected) { + mStartExtendedIndex = mSelectedIndex; + mEndExtendedIndex = kNothingSelected; + } else { + if (mSelectedIndex == mOldSelectedIndex) { + mEndExtendedIndex = kNothingSelected; + } else { + mEndExtendedIndex = mSelectedIndex; + } + ExtendedSelection(mStartExtendedIndex, mEndExtendedIndex, PR_FALSE, PR_TRUE); + } } else { if (mStartExtendedIndex < mEndExtendedIndex) { if (mSelectedIndex < mStartExtendedIndex) { @@ -1164,7 +1178,11 @@ nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) mEndExtendedIndex = mSelectedIndex; } else if (mSelectedIndex < mEndExtendedIndex) { ExtendedSelection(mSelectedIndex+1, mEndExtendedIndex, PR_FALSE, PR_FALSE); - mEndExtendedIndex = mSelectedIndex; + if (mSelectedIndex == mStartExtendedIndex) { + mEndExtendedIndex = kNothingSelected; + } else { + mEndExtendedIndex = mSelectedIndex; + } } } else if (mStartExtendedIndex > mEndExtendedIndex) { if (mSelectedIndex > mStartExtendedIndex) { @@ -1175,7 +1193,11 @@ nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) mEndExtendedIndex = mSelectedIndex; } else if (mSelectedIndex > mEndExtendedIndex) { ExtendedSelection(mEndExtendedIndex, mSelectedIndex-1, PR_FALSE, PR_FALSE); - mEndExtendedIndex = mSelectedIndex; + if (mSelectedIndex == mStartExtendedIndex) { + mEndExtendedIndex = kNothingSelected; + } else { + mEndExtendedIndex = mSelectedIndex; + } } } } @@ -1195,7 +1217,12 @@ nsListControlFrame::MultipleSelection(PRBool aIsShift, PRBool aIsControl) ClearSelection(); } } - +#ifdef DEBUG_rods + printf("mSelectedIndex: %d\n", mSelectedIndex); + printf("mOldSelectedIndex: %d\n", mOldSelectedIndex); + printf("mStartExtendedIndex: %d\n", mStartExtendedIndex); + printf("mEndExtendedIndex: %d\n", mEndExtendedIndex); +#endif } //--------------------------------------------------------- @@ -1716,19 +1743,21 @@ nsListControlFrame::SetContentSelected(PRInt32 aIndex, PRBool aSelected) if (content != nsnull) { nsCOMPtr presShell; mPresContext->GetShell(getter_AddRefs(presShell)); - nsIFrame * childframe; - nsresult result = presShell->GetPrimaryFrameFor(content, &childframe); - if (NS_SUCCEEDED(result) && childframe != nsnull) { - if (aSelected) { - DisplaySelected(content); - // Now that it is selected scroll to it - ScrollToFrame(content); + if (presShell) { + nsIFrame * childframe; + nsresult result = presShell->GetPrimaryFrameFor(content, &childframe); + if (NS_SUCCEEDED(result) && childframe != nsnull) { + if (aSelected) { + DisplaySelected(content); + // Now that it is selected scroll to it + ScrollToFrame(content); + } else { + DisplayDeselected(content); + } } else { - DisplayDeselected(content); + mDelayedIndexSetting = aIndex; + mDelayedValueSetting = aSelected; } - } else { - mDelayedIndexSetting = aIndex; - mDelayedValueSetting = aSelected; } NS_RELEASE(content); } @@ -1867,13 +1896,21 @@ nsListControlFrame::Reset(nsIPresContext* aPresContext) mSelectionCacheLength++; if (selected) { - mSelectedIndex = i; - SetContentSelected(i, PR_TRUE); - if (multiple) { - mStartExtendedIndex = i; - if (mEndExtendedIndex == kNothingSelected) { - mEndExtendedIndex = i; + if (mSelectedIndex == kNothingSelected || + (mSelectedIndex != kNothingSelected && multiple)) { + mSelectedIndex = i; + SetContentSelected(i, PR_TRUE); + if (multiple) { + mStartExtendedIndex = i; + if (mEndExtendedIndex == kNothingSelected) { + mEndExtendedIndex = i; + } } + } else { + SetContentSelected(mSelectedIndex, PR_FALSE); + mSelectionCache->ReplaceElementAt((void*)PR_FALSE, mSelectedIndex); + mSelectedIndex = i; + SetContentSelected(i, PR_TRUE); } } } @@ -2330,6 +2367,119 @@ nsListControlFrame::RemoveOption(nsIPresContext* aPresContext, PRInt32 aIndex) return NS_OK; } +#ifdef FIX_FOR_BUG_50376 +//------------------------------------------------------------------- +nsresult nsListControlFrame::GetPresStateAndValueArray(nsISupportsArray ** aSuppArray) +{ + // Basically we need to check for and/or create + // both the PresState and the Supports Array + // There may already be a no PresState and no Supports Array + // or there may be PresState and no Supports Array + // or there may be both + + // So assume we need to create the supports array and + //flip it off if we don't + PRBool createSupportsArray = PR_TRUE; + + nsresult res = NS_ERROR_FAILURE; + if (mPresState) { + nsCOMPtr supp; + mPresState->GetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("selecteditems"), getter_AddRefs(supp)); + if (supp) { + res = supp->QueryInterface(NS_GET_IID(nsISupportsArray), (void**)aSuppArray); + if (NS_FAILED(res)) { + return res; + } + createSupportsArray = PR_FALSE; + } + } else { + NS_NewPresState(getter_AddRefs(mPresState)); + } + + if (createSupportsArray) { + res = NS_NewISupportsArray(aSuppArray); + if (NS_SUCCEEDED(res)) { + res = mPresState->SetStatePropertyAsSupports(NS_ConvertASCIItoUCS2("selecteditems"), *aSuppArray); + } + } + return res; +} + +//------------------------------------------------------------------- +nsresult nsListControlFrame::SetSelectionInPresState(PRInt32 aIndex, PRBool aValue) +{ + // if there is no PresState and we ned to remove it + // from the PresState, then there is nothing to do + if (!mPresState && !aValue) { + return NS_OK; + } + + nsCOMPtr suppArray; + nsresult res = GetPresStateAndValueArray(getter_AddRefs(suppArray)); + + if (NS_FAILED(res) || !suppArray) + return res; + + if (aValue) { + PRUint32 count; + suppArray->Count(&count); + return SetOptionIntoPresState(suppArray, aIndex, count); + } else { + return RemoveOptionFromPresState(suppArray, aIndex); + } + +} + +//------------------------------------------------------------------- +nsresult nsListControlFrame::RemoveOptionFromPresState(nsISupportsArray * aSuppArray, + PRInt32 aIndex) +{ + NS_ENSURE_ARG_POINTER(aSuppArray); + nsresult res = NS_ERROR_FAILURE; + PRUint32 count; + aSuppArray->Count(&count); + nsCOMPtr thisVal; + for (PRUint32 i=0; i suppval = getter_AddRefs(aSuppArray->ElementAt(i)); + thisVal = do_QueryInterface(suppval); + if (thisVal) { + PRInt32 optIndex; + res = thisVal->GetData(&optIndex); + if (NS_SUCCEEDED(res)) { + if (optIndex == aIndex) { + aSuppArray->RemoveElementAt(i); + return NS_OK; + } + } + } else { + res = NS_ERROR_UNEXPECTED; + } + if (NS_FAILED(res)) break; + } + return res; +} + +//------------------------------------------------------------------- +nsresult nsListControlFrame::SetOptionIntoPresState(nsISupportsArray * aSuppArray, + PRInt32 aIndex, + PRInt32 anItemNum) +{ + NS_ENSURE_ARG_POINTER(aSuppArray); + nsCOMPtr thisVal; + nsresult res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, + nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(thisVal)); + if (NS_SUCCEEDED(res) && thisVal) { + res = thisVal->SetData(aIndex); + if (NS_SUCCEEDED(res)) { + PRBool okay = aSuppArray->InsertElementAt((nsISupports *)thisVal, anItemNum); + if (!okay) res = NS_ERROR_OUT_OF_MEMORY; // Most likely cause; + } + } + return res; +} + +#endif // FIX_FOR_BUG_50376 + //--------------------------------------------------------- // Select the specified item in the listbox using control logic. // If it a single selection listbox the previous selection will be @@ -2337,6 +2487,12 @@ nsListControlFrame::RemoveOption(nsIPresContext* aPresContext, PRInt32 aIndex) NS_IMETHODIMP nsListControlFrame::SetOptionSelected(PRInt32 aIndex, PRBool aValue) { +#ifdef FIX_FOR_BUG_50376 + if (!mIsAllFramesHere && !mHasBeenInitialized) { + return SetSelectionInPresState(aIndex, aValue); + } +#endif // FIX_FOR_BUG_50376 + PRBool multiple; nsresult rv = GetMultiple(&multiple); if (NS_SUCCEEDED(rv)) { @@ -2688,10 +2844,12 @@ nsListControlFrame::AboutToDropDown() //--------------------------------------------------------- // We are about to be rolledup from the outside (ComboboxFrame) -// this is a "cancelled" action not a selected action 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(); return NS_OK; } @@ -2824,6 +2982,9 @@ void nsListControlFrame::ResetSelectedItem() { if (mIsAllFramesHere) { ToggleSelected(mSelectedIndexWhenPoppedDown); + if (IsInDropDownMode() == PR_TRUE) { + mComboboxFrame->ListWasSelected(mPresContext, PR_TRUE); + } } } @@ -2862,7 +3023,7 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent) // if a right button click is on the combobox itself // or on the select when in listbox mode, then let the click through if (!IsLeftButton(aMouseEvent)) { - if (IsInDropDownMode()) { + if (IsInDropDownMode() == PR_TRUE) { if (!IsClickingInCombobox(aMouseEvent)) { aMouseEvent->PreventDefault(); aMouseEvent->PreventCapture(); @@ -2887,14 +3048,15 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent) PRBool optionIsDisabled; if (NS_OK == IsTargetOptionDisabled(optionIsDisabled)) { if (optionIsDisabled) { - if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) { + if (IsInDropDownMode() == PR_TRUE) { ResetSelectedItem(); - mComboboxFrame->ListWasSelected(mPresContext, PR_FALSE); - } + } else { + SetContentSelected(mSelectedIndex, PR_FALSE); + mSelectedIndex = kNothingSelected; + } REFLOW_DEBUG_MSG(">>>>>> Option is disabled"); mButtonDown = PR_FALSE; CaptureMouseEvents(mPresContext, PR_FALSE); - SetContentSelected(mSelectedIndex, PR_FALSE); return NS_OK; } } @@ -3165,7 +3327,7 @@ nsListControlFrame::MouseMove(nsIDOMEvent* aMouseEvent) NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null."); //REFLOW_DEBUG_MSG("MouseMove\n"); - if (mComboboxFrame) { // Synonym for IsInDropDownMode() + if (IsInDropDownMode() == PR_TRUE) { PRBool isDroppedDown = PR_FALSE; mComboboxFrame->IsDroppedDown(&isDroppedDown); if (isDroppedDown) { @@ -3198,7 +3360,7 @@ nsListControlFrame::DragMove(nsIDOMEvent* aMouseEvent) NS_ASSERTION(aMouseEvent != nsnull, "aMouseEvent is null."); //REFLOW_DEBUG_MSG("DragMove\n"); - if (!mComboboxFrame) { // Synonym for IsInDropDownMode() + if (IsInDropDownMode() == PR_FALSE) { // check to make sure we are a mulitple select list PRBool multipleSelections = PR_FALSE; GetMultiple(&multipleSelections); @@ -3477,9 +3639,26 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) PRBool isAlt = PR_FALSE; PRBool isMeta = PR_FALSE; keyEvent->GetCtrlKey(&isControl); - keyEvent->GetAltKey(&isAlt); keyEvent->GetMetaKey(&isMeta); - if (isControl || isAlt || isMeta) { + if (isControl || isMeta) { + return NS_OK; + } + + keyEvent->GetAltKey(&isAlt); + // Fix for Bug 62425 + if (isAlt) { +#ifdef FIX_FOR_BUG_62425 + if (code == nsIDOMKeyEvent::DOM_VK_UP || code == nsIDOMKeyEvent::DOM_VK_DOWN) { + if (IsInDropDownMode() == PR_TRUE) { + PRBool isDroppedDown; + mComboboxFrame->IsDroppedDown(&isDroppedDown); + mComboboxFrame->ShowDropDown(!isDroppedDown); + aKeyEvent->PreventDefault(); + aKeyEvent->PreventCapture(); + aKeyEvent->PreventBubble(); + } + } +#endif return NS_OK; } @@ -3543,9 +3722,9 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) case nsIDOMKeyEvent::DOM_VK_RETURN: { if (mComboboxFrame != nsnull) { - PRBool isDroppedDown; - mComboboxFrame->IsDroppedDown(&isDroppedDown); - if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) { + if (IsInDropDownMode() == PR_TRUE) { + PRBool isDroppedDown; + mComboboxFrame->IsDroppedDown(&isDroppedDown); mComboboxFrame->ListWasSelected(mPresContext, isDroppedDown); } else { UpdateSelection(PR_TRUE, PR_FALSE, mContent); @@ -3554,9 +3733,8 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) } break; case nsIDOMKeyEvent::DOM_VK_ESCAPE: { - if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) { + if (IsInDropDownMode() == PR_TRUE) { ResetSelectedItem(); - mComboboxFrame->ListWasSelected(mPresContext, PR_FALSE); } } break; @@ -3600,6 +3778,7 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) default: { // Select option with this as the first character // XXX Not I18N compliant + code = (PRUint32)nsCRT::ToLower((PRUnichar)code); PRInt32 selectedIndex = (mSelectedIndex == kNothingSelected ? 0 : mSelectedIndex+1) % numOptions; PRInt32 startedAtIndex = selectedIndex; PRBool loopedAround = PR_FALSE; @@ -3665,7 +3844,7 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent) // XXX - Are we cover up a problem here??? // Why aren't they getting flushed each time? // because this isn't needed for Gfx - if (IsInDropDownMode() == PR_TRUE && mComboboxFrame) { + if (IsInDropDownMode() == PR_TRUE) { nsCOMPtr presShell; mPresContext->GetShell(getter_AddRefs(presShell)); presShell->FlushPendingNotifications(); @@ -3704,6 +3883,9 @@ nsListControlFrame::SaveStateInternal(nsIPresContext* aPresContext, nsIPresState PRBool selected = PR_FALSE; res = GetOptionSelected(i, &selected); if (NS_SUCCEEDED(res) && selected) { +#ifdef FIX_FOR_BUG_50376 + res = SetOptionIntoPresState(value, i, j++); +#else nsCOMPtr thisVal; res = nsComponentManager::CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, nsnull, NS_GET_IID(nsISupportsPRInt32), (void**)getter_AddRefs(thisVal)); @@ -3714,6 +3896,7 @@ nsListControlFrame::SaveStateInternal(nsIPresContext* aPresContext, nsIPresState if (!okay) res = NS_ERROR_OUT_OF_MEMORY; // Most likely cause; } } +#endif } if (!NS_SUCCEEDED(res)) break; } diff --git a/layout/html/forms/src/nsListControlFrame.h b/layout/html/forms/src/nsListControlFrame.h index ba6a026f87f3..b1c1ebc17328 100644 --- a/layout/html/forms/src/nsListControlFrame.h +++ b/layout/html/forms/src/nsListControlFrame.h @@ -152,6 +152,8 @@ protected: /** * Frame-based listbox. */ +#define FIX_FOR_BUG_50376 + class nsListControlFrame : public nsScrollFrame, public nsIFormControlFrame, @@ -293,6 +295,16 @@ protected: void AdjustIndexForDisabledOpt(PRInt32 &anNewIndex, PRInt32 &anOldIndex, PRBool &aDoSetNewIndex, PRBool &aWasDisabled, PRInt32 aNumOptions, PRInt32 aDoAdjustInc, PRInt32 aDoAdjustIncNext); +#ifdef FIX_FOR_BUG_50376 + // PresState Helper Methods + nsresult GetPresStateAndValueArray(nsISupportsArray ** aSuppArray); + nsresult SetOptionIntoPresState(nsISupportsArray * aSuppArray, + PRInt32 aIndex, + PRInt32 anItemNum); + nsresult SetSelectionInPresState(PRInt32 aIndex, PRBool aValue); + nsresult RemoveOptionFromPresState(nsISupportsArray * aSuppArray, + PRInt32 aIndex); +#endif nsListControlFrame(); virtual ~nsListControlFrame();