diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index 9032a0b5f55..1e4e4521196 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -60,8 +60,10 @@ #include "nsINodeInfo.h" #include "nsIScrollableFrame.h" #include "nsIScrollableView.h" +#include "nsListControlFrame.h" #include "nsIElementFactory.h" #include "nsContentCID.h" + static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID); static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID); @@ -94,6 +96,7 @@ const PRInt32 kSizeNotSet = -1; // static class data member for Bug 32920 nsComboboxControlFrame * nsComboboxControlFrame::mFocused = nsnull; +nscoord nsComboboxControlFrame::mCachedScrollbarWidth = kSizeNotSet; nsresult NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aStateFlags) @@ -1205,24 +1208,25 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // the default size of the of scrollbar // that will be the default width of the dropdown button // the height will be the height of the text - nscoord scrollbarWidth = -1; - nsCOMPtr dx; - aPresContext->GetDeviceContext(getter_AddRefs(dx)); - if (dx) { - // Get the width in Device pixels (in this case screen) - SystemAttrStruct info; - dx->GetSystemAttribute(eSystemAttr_Size_ScrollbarWidth, &info); - // Get the pixels to twips conversion for the current device (screen or printer) - float p2t; - aPresContext->GetPixelsToTwips(&p2t); - // Get the scale factor for mapping from one device (screen) - // to another device (screen or printer) - // Typically when it is a screen the scale 1.0 - // when it is a printer is could be anything - float scale; - dx->GetCanonicalPixelScale(scale); - scrollbarWidth = NSIntPixelsToTwips(info.mSize, p2t*scale); - } + if (mCachedScrollbarWidth == kSizeNotSet) { + nsCOMPtr dx; + aPresContext->GetDeviceContext(getter_AddRefs(dx)); + if (dx) { + // Get the width in Device pixels (in this case screen) + SystemAttrStruct info; + dx->GetSystemAttribute(eSystemAttr_Size_ScrollbarWidth, &info); + // Get the pixels to twips conversion for the current device (screen or printer) + float p2t; + aPresContext->GetPixelsToTwips(&p2t); + // Get the scale factor for mapping from one device (screen) + // to another device (screen or printer) + // Typically when it is a screen the scale 1.0 + // when it is a printer is could be anything + float scale; + dx->GetCanonicalPixelScale(scale); + mCachedScrollbarWidth = NSIntPixelsToTwips(info.mSize, p2t*scale); + } + } // set up a new reflow state for use throughout nsHTMLReflowState firstPassState(aReflowState); @@ -1257,7 +1261,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, REFLOW_DEBUG_MSG("------------Reflowing AreaFrame and bailing----\n\n"); ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, mDisplayFrame, mButtonFrame, mItemDisplayWidth, - scrollbarWidth, borderPadding); + mCachedScrollbarWidth, borderPadding); REFLOW_COUNTER(); UNCONSTRAINED_CHECK(); REFLOW_DEBUG_MSG3("&** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); @@ -1310,7 +1314,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // Do simple reflow and bail out ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, mDisplayFrame, mButtonFrame, - mItemDisplayWidth, scrollbarWidth, borderPadding, kSizeNotSet, PR_TRUE); + mItemDisplayWidth, mCachedScrollbarWidth, borderPadding, kSizeNotSet, PR_TRUE); REFLOW_DEBUG_MSG3("+** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); REFLOW_COUNTER(); UNCONSTRAINED_CHECK(); @@ -1379,11 +1383,18 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, if ((mCachedUncDropdownSize.width == kSizeNotSet && mCachedUncDropdownSize.height == kSizeNotSet) || forceReflow) { REFLOW_DEBUG_MSG3("---Re %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); + + // Tell it we are doing the first pass, which means it will + // do the unconstained reflow and skip the second reflow this time around + nsListControlFrame * lcf = NS_STATIC_CAST(nsListControlFrame*, mDropdownFrame); + lcf->SetPassId(1); // A width has not been specified for the select so size the display area // to match the width of the longest item in the drop-down list. The dropdown // list has already been reflowed and sized to shrink around its contents above. ReflowComboChildFrame(mDropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + lcf->SetPassId(0); // reset it back + if (forceReflow) { mCachedUncDropdownSize.width = dropdownDesiredSize.width; mCachedUncDropdownSize.height = dropdownDesiredSize.height; @@ -1466,8 +1477,8 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // the variable "size" will now be // the default size of the dropdown btn - if (scrollbarWidth > 0) { - size.width = scrollbarWidth; + if (mCachedScrollbarWidth > 0) { + size.width = mCachedScrollbarWidth; } // Get the border and padding for the dropdown @@ -1524,7 +1535,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // this reflows and makes and last minute adjustments ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, mButtonFrame, mItemDisplayWidth, scrollbarWidth, + mDisplayFrame, mButtonFrame, mItemDisplayWidth, mCachedScrollbarWidth, borderPadding, size.height); // The dropdown was reflowed UNCONSTRAINED before, now we need to check to see @@ -1534,17 +1545,21 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // than for any particular item in the dropdown. So, if the new size of combobox // is smaller than the dropdown, that is OK, The dropdown MUST always be either the same //size as the combo or larger if necessary -#if 1 if (aDesiredSize.width > dropdownDesiredSize.width) { if (eReflowReason_Initial == firstPassState.reason) { firstPassState.reason = eReflowReason_Resize; } REFLOW_DEBUG_MSG3("*** Reflowing ListBox to width: %d it was %d\n", PX(aDesiredSize.width), PX(dropdownDesiredSize.width)); + + // Tell it we are doing the second pass, which means we will skip + // doing the unconstained reflow, we already know that size + nsListControlFrame * lcf = NS_STATIC_CAST(nsListControlFrame*, mDropdownFrame); + lcf->SetPassId(2); // Reflow the dropdown list to match the width of the display + button ReflowComboChildFrame(mDropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + lcf->SetPassId(0); // reset it back } -#endif #else // DO_NEW_REFLOW @@ -1573,7 +1588,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // this reflows and makes and last minute adjustments ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, mButtonFrame, mItemDisplayWidth, scrollbarWidth, + mDisplayFrame, mButtonFrame, mItemDisplayWidth, mCachedScrollbarWidth, borderPadding, aDesiredSize.height- borderPadding.top - borderPadding.bottom - dspBorderPadding.top - dspBorderPadding.bottom); diff --git a/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index 86607ea0544..15f39dc57af 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -278,6 +278,7 @@ protected: // static class data member for Bug 32920 // only one control can be focused at a time static nsComboboxControlFrame * mFocused; + static nscoord mCachedScrollbarWidth; #ifdef DO_REFLOW_COUNTER PRInt32 mReflowId; diff --git a/mozilla/layout/forms/nsListControlFrame.cpp b/mozilla/layout/forms/nsListControlFrame.cpp index facc23942f3..49bfabad14e 100644 --- a/mozilla/layout/forms/nsListControlFrame.cpp +++ b/mozilla/layout/forms/nsListControlFrame.cpp @@ -242,6 +242,7 @@ nsListControlFrame::nsListControlFrame() mCachedUnconstrainedSize.height = -1; mOverrideReflowOpt = PR_FALSE; + mPassId = 0; REFLOW_COUNTER_INIT() } @@ -611,62 +612,46 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, } } - nsresult res = nsScrollFrame::Reflow(aPresContext, - scrolledAreaDesiredSize, - firstPassState, - aStatus); - if (NS_FAILED(res)) { - NS_ASSERTION(aDesiredSize.width < 100000, "Width is still NS_UNCONSTRAINEDSIZE"); - NS_ASSERTION(aDesiredSize.height < 100000, "Height is still NS_UNCONSTRAINEDSIZE"); - return res; + if (mPassId == 0 || mPassId == 1) { + nsresult res = nsScrollFrame::Reflow(aPresContext, + scrolledAreaDesiredSize, + firstPassState, + aStatus); + if (NS_FAILED(res)) { + NS_ASSERTION(aDesiredSize.width < 100000, "Width is still NS_UNCONSTRAINEDSIZE"); + NS_ASSERTION(aDesiredSize.height < 100000, "Height is still NS_UNCONSTRAINEDSIZE"); + return res; + } + mCachedUnconstrainedSize.width = scrolledAreaDesiredSize.width; + mCachedUnconstrainedSize.height = scrolledAreaDesiredSize.height; + mCachedDesiredMaxSize.width = scrolledAreaDesiredSize.maxElementSize->width; + mCachedDesiredMaxSize.height = scrolledAreaDesiredSize.maxElementSize->height; + } else { + scrolledAreaDesiredSize.width = mCachedUnconstrainedSize.width; + scrolledAreaDesiredSize.height = mCachedUnconstrainedSize.height; + scrolledAreaDesiredSize.maxElementSize->width = mCachedDesiredMaxSize.width; + scrolledAreaDesiredSize.maxElementSize->height = mCachedDesiredMaxSize.height; } - nsIScrollableFrame * scrollableFrame = nsnull; - nsRect scrolledRect; - if (NS_SUCCEEDED(QueryInterface(NS_GET_IID(nsIScrollableFrame), (void**)&scrollableFrame))) { - nsIFrame * scrolledFrame; - scrollableFrame->GetScrolledFrame(aPresContext, scrolledFrame); - NS_ASSERTION(scrolledFrame != nsnull, "Must have scrollable frame"); - scrolledFrame->GetRect(scrolledRect); - } else { - NS_ASSERTION(scrollableFrame != nsnull, "Must have scrollableFrame frame"); - } // Compute the bounding box of the contents of the list using the area // calculated by the first reflow as a starting point. // // The nsScrollFrame::REflow adds in the scrollbar width and border dimensions // to the maxElementSize, so these need to be subtracted - nscoord scrolledAreaWidth = scrolledAreaDesiredSize.maxElementSize->width; - nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height; + nscoord scrolledAreaWidth = scrolledAreaDesiredSize.maxElementSize->width - + (aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right); + nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height - + (aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom); - // Keep the oringal values + // Set up max values mMaxWidth = scrolledAreaWidth; - mMaxHeight = scrolledAreaDesiredSize.maxElementSize->height; - - // The first reflow produces a box with the scrollbar width and borders - // added in so we need to subtract them out. - - // Retrieve the scrollbar's width and height - float sbWidth = 0.0; - float sbHeight = 0.0;; - nsCOMPtr dc; - aPresContext->GetDeviceContext(getter_AddRefs(dc)); - dc->GetScrollBarDimensions(sbWidth, sbHeight); - // Convert to nscoord's by rounding - nscoord scrollbarWidth = NSToCoordRound(sbWidth); - //nscoord scrollbarHeight = NSToCoordRound(sbHeight); - - mMaxWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - mMaxHeight -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; + mMaxHeight = scrolledAreaDesiredSize.maxElementSize->height - + (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 -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - scrolledAreaHeight -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - nscoord visibleWidth = 0; if (isInDropDownMode) { if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { @@ -679,7 +664,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { visibleWidth = scrolledAreaWidth; } else { - visibleWidth = aReflowState.mComputedWidth;// - scrollbarWidth; + visibleWidth = aReflowState.mComputedWidth; } } @@ -870,9 +855,16 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, secondPassState.mComputedHeight = visibleHeight; secondPassState.reason = eReflowReason_Resize; - nsScrollFrame::Reflow(aPresContext, aDesiredSize, secondPassState, aStatus); - + if (mPassId == 0 || mPassId == 2) { + nsScrollFrame::Reflow(aPresContext, aDesiredSize, secondPassState, aStatus); // Set the max element size to be the same as the desired element size. + } else { + aDesiredSize.width = visibleWidth; + aDesiredSize.height = visibleHeight; + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + } + if (nsnull != aDesiredSize.maxElementSize) { aDesiredSize.maxElementSize->width = aDesiredSize.width; aDesiredSize.maxElementSize->height = aDesiredSize.height; @@ -880,7 +872,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, aStatus = NS_FRAME_COMPLETE; -#ifdef DEBUG_rods +#ifdef DEBUG_rodsX if (!isInDropDownMode) { PRInt32 numRows = 1; GetSizeAttribute(&numRows); diff --git a/mozilla/layout/forms/nsListControlFrame.h b/mozilla/layout/forms/nsListControlFrame.h index 6ca490ed711..4f779c73b31 100644 --- a/mozilla/layout/forms/nsListControlFrame.h +++ b/mozilla/layout/forms/nsListControlFrame.h @@ -27,8 +27,8 @@ #endif #ifdef DEBUG_rods -#define DO_REFLOW_DEBUG -#define DO_REFLOW_COUNTER +//#define DO_REFLOW_DEBUG +//#define DO_REFLOW_COUNTER //#define DO_UNCONSTRAINED_CHECK //#define DO_PIXELS #endif @@ -290,6 +290,9 @@ public: nsCWeakReferent *WeakReferent() { return &mWeakReferent; } + // Helper + void SetPassId(PRInt16 aId) { mPassId = aId; } + protected: NS_IMETHOD GetSelectedIndexFromDOM(PRInt32* aIndex); // from DOM @@ -402,6 +405,9 @@ protected: // XXX temprary only until full system mouse capture works PRBool mIsScrollbarVisible; + PRInt16 mPassId; + nsSize mCachedDesiredMaxSize; + //Resize Reflow OpitmizationSize; nsSize mCacheSize; nsSize mCachedMaxElementSize; diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index 9032a0b5f55..1e4e4521196 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -60,8 +60,10 @@ #include "nsINodeInfo.h" #include "nsIScrollableFrame.h" #include "nsIScrollableView.h" +#include "nsListControlFrame.h" #include "nsIElementFactory.h" #include "nsContentCID.h" + static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID); static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID); @@ -94,6 +96,7 @@ const PRInt32 kSizeNotSet = -1; // static class data member for Bug 32920 nsComboboxControlFrame * nsComboboxControlFrame::mFocused = nsnull; +nscoord nsComboboxControlFrame::mCachedScrollbarWidth = kSizeNotSet; nsresult NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aStateFlags) @@ -1205,24 +1208,25 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // the default size of the of scrollbar // that will be the default width of the dropdown button // the height will be the height of the text - nscoord scrollbarWidth = -1; - nsCOMPtr dx; - aPresContext->GetDeviceContext(getter_AddRefs(dx)); - if (dx) { - // Get the width in Device pixels (in this case screen) - SystemAttrStruct info; - dx->GetSystemAttribute(eSystemAttr_Size_ScrollbarWidth, &info); - // Get the pixels to twips conversion for the current device (screen or printer) - float p2t; - aPresContext->GetPixelsToTwips(&p2t); - // Get the scale factor for mapping from one device (screen) - // to another device (screen or printer) - // Typically when it is a screen the scale 1.0 - // when it is a printer is could be anything - float scale; - dx->GetCanonicalPixelScale(scale); - scrollbarWidth = NSIntPixelsToTwips(info.mSize, p2t*scale); - } + if (mCachedScrollbarWidth == kSizeNotSet) { + nsCOMPtr dx; + aPresContext->GetDeviceContext(getter_AddRefs(dx)); + if (dx) { + // Get the width in Device pixels (in this case screen) + SystemAttrStruct info; + dx->GetSystemAttribute(eSystemAttr_Size_ScrollbarWidth, &info); + // Get the pixels to twips conversion for the current device (screen or printer) + float p2t; + aPresContext->GetPixelsToTwips(&p2t); + // Get the scale factor for mapping from one device (screen) + // to another device (screen or printer) + // Typically when it is a screen the scale 1.0 + // when it is a printer is could be anything + float scale; + dx->GetCanonicalPixelScale(scale); + mCachedScrollbarWidth = NSIntPixelsToTwips(info.mSize, p2t*scale); + } + } // set up a new reflow state for use throughout nsHTMLReflowState firstPassState(aReflowState); @@ -1257,7 +1261,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, REFLOW_DEBUG_MSG("------------Reflowing AreaFrame and bailing----\n\n"); ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, mDisplayFrame, mButtonFrame, mItemDisplayWidth, - scrollbarWidth, borderPadding); + mCachedScrollbarWidth, borderPadding); REFLOW_COUNTER(); UNCONSTRAINED_CHECK(); REFLOW_DEBUG_MSG3("&** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); @@ -1310,7 +1314,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // Do simple reflow and bail out ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, mDisplayFrame, mButtonFrame, - mItemDisplayWidth, scrollbarWidth, borderPadding, kSizeNotSet, PR_TRUE); + mItemDisplayWidth, mCachedScrollbarWidth, borderPadding, kSizeNotSet, PR_TRUE); REFLOW_DEBUG_MSG3("+** Done nsCCF DW: %d DH: %d\n\n", PX(aDesiredSize.width), PX(aDesiredSize.height)); REFLOW_COUNTER(); UNCONSTRAINED_CHECK(); @@ -1379,11 +1383,18 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, if ((mCachedUncDropdownSize.width == kSizeNotSet && mCachedUncDropdownSize.height == kSizeNotSet) || forceReflow) { REFLOW_DEBUG_MSG3("---Re %d,%d\n", PX(mCachedUncDropdownSize.width), PX(mCachedUncDropdownSize.height)); + + // Tell it we are doing the first pass, which means it will + // do the unconstained reflow and skip the second reflow this time around + nsListControlFrame * lcf = NS_STATIC_CAST(nsListControlFrame*, mDropdownFrame); + lcf->SetPassId(1); // A width has not been specified for the select so size the display area // to match the width of the longest item in the drop-down list. The dropdown // list has already been reflowed and sized to shrink around its contents above. ReflowComboChildFrame(mDropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + lcf->SetPassId(0); // reset it back + if (forceReflow) { mCachedUncDropdownSize.width = dropdownDesiredSize.width; mCachedUncDropdownSize.height = dropdownDesiredSize.height; @@ -1466,8 +1477,8 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // the variable "size" will now be // the default size of the dropdown btn - if (scrollbarWidth > 0) { - size.width = scrollbarWidth; + if (mCachedScrollbarWidth > 0) { + size.width = mCachedScrollbarWidth; } // Get the border and padding for the dropdown @@ -1524,7 +1535,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // this reflows and makes and last minute adjustments ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, mButtonFrame, mItemDisplayWidth, scrollbarWidth, + mDisplayFrame, mButtonFrame, mItemDisplayWidth, mCachedScrollbarWidth, borderPadding, size.height); // The dropdown was reflowed UNCONSTRAINED before, now we need to check to see @@ -1534,17 +1545,21 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // than for any particular item in the dropdown. So, if the new size of combobox // is smaller than the dropdown, that is OK, The dropdown MUST always be either the same //size as the combo or larger if necessary -#if 1 if (aDesiredSize.width > dropdownDesiredSize.width) { if (eReflowReason_Initial == firstPassState.reason) { firstPassState.reason = eReflowReason_Resize; } REFLOW_DEBUG_MSG3("*** Reflowing ListBox to width: %d it was %d\n", PX(aDesiredSize.width), PX(dropdownDesiredSize.width)); + + // Tell it we are doing the second pass, which means we will skip + // doing the unconstained reflow, we already know that size + nsListControlFrame * lcf = NS_STATIC_CAST(nsListControlFrame*, mDropdownFrame); + lcf->SetPassId(2); // Reflow the dropdown list to match the width of the display + button ReflowComboChildFrame(mDropdownFrame, aPresContext, dropdownDesiredSize, firstPassState, aStatus, aDesiredSize.width, NS_UNCONSTRAINEDSIZE); + lcf->SetPassId(0); // reset it back } -#endif #else // DO_NEW_REFLOW @@ -1573,7 +1588,7 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, // this reflows and makes and last minute adjustments ReflowCombobox(aPresContext, firstPassState, aDesiredSize, aStatus, - mDisplayFrame, mButtonFrame, mItemDisplayWidth, scrollbarWidth, + mDisplayFrame, mButtonFrame, mItemDisplayWidth, mCachedScrollbarWidth, borderPadding, aDesiredSize.height- borderPadding.top - borderPadding.bottom - dspBorderPadding.top - dspBorderPadding.bottom); diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h index 86607ea0544..15f39dc57af 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h @@ -278,6 +278,7 @@ protected: // static class data member for Bug 32920 // only one control can be focused at a time static nsComboboxControlFrame * mFocused; + static nscoord mCachedScrollbarWidth; #ifdef DO_REFLOW_COUNTER PRInt32 mReflowId; diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp index facc23942f3..49bfabad14e 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp @@ -242,6 +242,7 @@ nsListControlFrame::nsListControlFrame() mCachedUnconstrainedSize.height = -1; mOverrideReflowOpt = PR_FALSE; + mPassId = 0; REFLOW_COUNTER_INIT() } @@ -611,62 +612,46 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, } } - nsresult res = nsScrollFrame::Reflow(aPresContext, - scrolledAreaDesiredSize, - firstPassState, - aStatus); - if (NS_FAILED(res)) { - NS_ASSERTION(aDesiredSize.width < 100000, "Width is still NS_UNCONSTRAINEDSIZE"); - NS_ASSERTION(aDesiredSize.height < 100000, "Height is still NS_UNCONSTRAINEDSIZE"); - return res; + if (mPassId == 0 || mPassId == 1) { + nsresult res = nsScrollFrame::Reflow(aPresContext, + scrolledAreaDesiredSize, + firstPassState, + aStatus); + if (NS_FAILED(res)) { + NS_ASSERTION(aDesiredSize.width < 100000, "Width is still NS_UNCONSTRAINEDSIZE"); + NS_ASSERTION(aDesiredSize.height < 100000, "Height is still NS_UNCONSTRAINEDSIZE"); + return res; + } + mCachedUnconstrainedSize.width = scrolledAreaDesiredSize.width; + mCachedUnconstrainedSize.height = scrolledAreaDesiredSize.height; + mCachedDesiredMaxSize.width = scrolledAreaDesiredSize.maxElementSize->width; + mCachedDesiredMaxSize.height = scrolledAreaDesiredSize.maxElementSize->height; + } else { + scrolledAreaDesiredSize.width = mCachedUnconstrainedSize.width; + scrolledAreaDesiredSize.height = mCachedUnconstrainedSize.height; + scrolledAreaDesiredSize.maxElementSize->width = mCachedDesiredMaxSize.width; + scrolledAreaDesiredSize.maxElementSize->height = mCachedDesiredMaxSize.height; } - nsIScrollableFrame * scrollableFrame = nsnull; - nsRect scrolledRect; - if (NS_SUCCEEDED(QueryInterface(NS_GET_IID(nsIScrollableFrame), (void**)&scrollableFrame))) { - nsIFrame * scrolledFrame; - scrollableFrame->GetScrolledFrame(aPresContext, scrolledFrame); - NS_ASSERTION(scrolledFrame != nsnull, "Must have scrollable frame"); - scrolledFrame->GetRect(scrolledRect); - } else { - NS_ASSERTION(scrollableFrame != nsnull, "Must have scrollableFrame frame"); - } // Compute the bounding box of the contents of the list using the area // calculated by the first reflow as a starting point. // // The nsScrollFrame::REflow adds in the scrollbar width and border dimensions // to the maxElementSize, so these need to be subtracted - nscoord scrolledAreaWidth = scrolledAreaDesiredSize.maxElementSize->width; - nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height; + nscoord scrolledAreaWidth = scrolledAreaDesiredSize.maxElementSize->width - + (aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right); + nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height - + (aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom); - // Keep the oringal values + // Set up max values mMaxWidth = scrolledAreaWidth; - mMaxHeight = scrolledAreaDesiredSize.maxElementSize->height; - - // The first reflow produces a box with the scrollbar width and borders - // added in so we need to subtract them out. - - // Retrieve the scrollbar's width and height - float sbWidth = 0.0; - float sbHeight = 0.0;; - nsCOMPtr dc; - aPresContext->GetDeviceContext(getter_AddRefs(dc)); - dc->GetScrollBarDimensions(sbWidth, sbHeight); - // Convert to nscoord's by rounding - nscoord scrollbarWidth = NSToCoordRound(sbWidth); - //nscoord scrollbarHeight = NSToCoordRound(sbHeight); - - mMaxWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - mMaxHeight -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; + mMaxHeight = scrolledAreaDesiredSize.maxElementSize->height - + (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 -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - scrolledAreaHeight -= aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - nscoord visibleWidth = 0; if (isInDropDownMode) { if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { @@ -679,7 +664,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { visibleWidth = scrolledAreaWidth; } else { - visibleWidth = aReflowState.mComputedWidth;// - scrollbarWidth; + visibleWidth = aReflowState.mComputedWidth; } } @@ -870,9 +855,16 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, secondPassState.mComputedHeight = visibleHeight; secondPassState.reason = eReflowReason_Resize; - nsScrollFrame::Reflow(aPresContext, aDesiredSize, secondPassState, aStatus); - + if (mPassId == 0 || mPassId == 2) { + nsScrollFrame::Reflow(aPresContext, aDesiredSize, secondPassState, aStatus); // Set the max element size to be the same as the desired element size. + } else { + aDesiredSize.width = visibleWidth; + aDesiredSize.height = visibleHeight; + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + } + if (nsnull != aDesiredSize.maxElementSize) { aDesiredSize.maxElementSize->width = aDesiredSize.width; aDesiredSize.maxElementSize->height = aDesiredSize.height; @@ -880,7 +872,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, aStatus = NS_FRAME_COMPLETE; -#ifdef DEBUG_rods +#ifdef DEBUG_rodsX if (!isInDropDownMode) { PRInt32 numRows = 1; GetSizeAttribute(&numRows); diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.h b/mozilla/layout/html/forms/src/nsListControlFrame.h index 6ca490ed711..4f779c73b31 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.h +++ b/mozilla/layout/html/forms/src/nsListControlFrame.h @@ -27,8 +27,8 @@ #endif #ifdef DEBUG_rods -#define DO_REFLOW_DEBUG -#define DO_REFLOW_COUNTER +//#define DO_REFLOW_DEBUG +//#define DO_REFLOW_COUNTER //#define DO_UNCONSTRAINED_CHECK //#define DO_PIXELS #endif @@ -290,6 +290,9 @@ public: nsCWeakReferent *WeakReferent() { return &mWeakReferent; } + // Helper + void SetPassId(PRInt16 aId) { mPassId = aId; } + protected: NS_IMETHOD GetSelectedIndexFromDOM(PRInt32* aIndex); // from DOM @@ -402,6 +405,9 @@ protected: // XXX temprary only until full system mouse capture works PRBool mIsScrollbarVisible; + PRInt16 mPassId; + nsSize mCachedDesiredMaxSize; + //Resize Reflow OpitmizationSize; nsSize mCacheSize; nsSize mCachedMaxElementSize;