Backing out patch for bug 108817 to test whether it causes the Tp regression.

This commit is contained in:
bzbarsky@mit.edu
2004-08-10 23:37:43 +00:00
parent ffc9fb9954
commit 213a1b9d91
4 changed files with 530 additions and 106 deletions

View File

@@ -90,6 +90,9 @@
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMKeyListener.h"
// Timer Includes
#include "nsITimer.h"
// Constants
const nscoord kMaxDropDownRows = 20; // This matches the setting for 4.x browsers
const PRInt32 kDefaultMultiselectHeight = 4; // This is compatible with 4.x browsers
@@ -279,21 +282,169 @@ if (aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE) { \
//-- Done with macros
//------------------------------------------------------
//---------------------------------------------------
//-- Update Timer Stuff
//---------------------------------------------------
class nsSelectUpdateTimer : public nsITimerCallback
{
public:
NS_DECL_ISUPPORTS
nsSelectUpdateTimer()
: mPresContext(nsnull), mDelay(0), mHasBeenNotified(PR_FALSE),
mItemsAdded(PR_FALSE), mItemsRemoved(PR_FALSE), mItemsInxSet(PR_FALSE)
{
}
virtual ~nsSelectUpdateTimer();
NS_DECL_NSITIMERCALLBACK
// Additional Methods
nsresult Start(nsPresContext *aPresContext)
{
mPresContext = aPresContext;
nsresult result = NS_OK;
if (!mTimer) {
mTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
if (NS_FAILED(result))
return result;
}
result = mTimer->InitWithCallback(this, mDelay, nsITimer::TYPE_ONE_SHOT);
if (mHasBeenNotified) {
mItemsAdded = PR_FALSE;
mItemsRemoved = PR_FALSE;
mItemsInxSet = PR_FALSE;
mHasBeenNotified = PR_FALSE;
mInxArray.Clear();
}
return result;
}
void Init(nsListControlFrame *aList, PRUint32 aDelay) { mListControl = aList; mDelay = aDelay; }
void Stop() { if (mTimer) mTimer->Cancel(); }
void AdjustIndexes(PRBool aInserted, PRInt32 aInx)
{
// remove the index from the list
if (!aInserted) {
PRInt32 inx = (PRInt32)mInxArray.IndexOf((void*)aInx);
if (inx > -1) {
mInxArray.RemoveElementAt(inx);
}
}
PRInt32 count = mInxArray.Count();
for (PRInt32 i=0;i<count;i++) {
PRInt32 inx = NS_PTR_TO_INT32(mInxArray[i]);
if (inx > aInx) {
mInxArray.ReplaceElementAt((void*)(inx+(aInserted?1:-1)), i);
}
}
}
void ItemAdded(PRInt32 aInx, PRInt32 aNumItems)
{
mItemsAdded = PR_TRUE;
if (mInxArray.Count() > 0 && aInx <= aNumItems-1) {
AdjustIndexes(PR_TRUE, aInx);
}
}
void ItemRemoved(PRInt32 aInx, PRInt32 aNumItems)
{
mItemsRemoved = PR_TRUE;
if (mInxArray.Count() > 0 && aInx <= aNumItems) {
AdjustIndexes(PR_FALSE, aInx);
}
}
void ItemIndexSet(PRInt32 aInx)
{
mItemsInxSet = PR_TRUE;
mInxArray.AppendElement((void*)aInx);
}
PRPackedBool HasBeenNotified() { return mHasBeenNotified; }
private:
nsListControlFrame * mListControl;
nsCOMPtr<nsITimer> mTimer;
nsPresContext* mPresContext;
PRUint32 mDelay;
PRPackedBool mHasBeenNotified;
PRPackedBool mItemsAdded;
PRPackedBool mItemsRemoved;
PRPackedBool mItemsInxSet;
nsVoidArray mInxArray;
};
NS_IMPL_ADDREF(nsSelectUpdateTimer)
NS_IMPL_RELEASE(nsSelectUpdateTimer)
NS_IMPL_QUERY_INTERFACE1(nsSelectUpdateTimer, nsITimerCallback)
nsresult NS_NewUpdateTimer(nsSelectUpdateTimer **aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
*aResult = (nsSelectUpdateTimer*) new nsSelectUpdateTimer;
if (!aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
// nsITimerCallback
NS_IMETHODIMP nsSelectUpdateTimer::Notify(nsITimer *timer)
{
if (mPresContext && mListControl && !mHasBeenNotified) {
mHasBeenNotified = PR_TRUE;
if (mItemsAdded || mItemsInxSet) {
mListControl->ResetList(mPresContext, &mInxArray);
} else {
mListControl->ItemsHaveBeenRemoved(mPresContext);
}
}
return NS_OK;
}
nsSelectUpdateTimer::~nsSelectUpdateTimer()
{
if (mTimer) {
mTimer->Cancel();
}
}
//---------------------------------------------------
//-- DONE: Update Timer Stuff
//---------------------------------------------------
//---------------------------------------------------------
nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
nsIDocument* aDocument)
: nsHTMLScrollFrame(aShell, PR_FALSE)
{
mComboboxFrame = nsnull;
mChangesSinceDragStart = PR_FALSE;
mButtonDown = PR_FALSE;
mMaxWidth = 0;
mMaxHeight = 0;
mPresContext = nsnull;
mIsAllContentHere = PR_FALSE;
mIsAllFramesHere = PR_FALSE;
mHasBeenInitialized = PR_FALSE;
mNeedToReset = PR_TRUE;
mDoneWithInitialReflow = PR_FALSE;
mCacheSize.width = -1;
mCacheSize.height = -1;
@@ -306,6 +457,7 @@ nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
mOverrideReflowOpt = PR_FALSE;
mPassId = 0;
mUpdateTimer = nsnull;
mDummyFrame = nsnull;
REFLOW_COUNTER_INIT()
@@ -315,8 +467,13 @@ nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
nsListControlFrame::~nsListControlFrame()
{
REFLOW_COUNTER_DUMP("nsLCF");
if (mUpdateTimer != nsnull) {
StopUpdateTimer();
NS_RELEASE(mUpdateTimer);
}
mComboboxFrame = nsnull;
NS_IF_RELEASE(mPresContext);
}
// for Bug 47302 (remove this comment later)
@@ -426,16 +583,15 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer
focusedIndex = mEndSelectionIndex;
}
nsPresContext* presContext = GetPresContext();
nsIScrollableView * scrollableView;
GetScrollableView(presContext, &scrollableView);
GetScrollableView(mPresContext, &scrollableView);
if (!scrollableView) return;
nsIPresShell *presShell = presContext->GetPresShell();
nsIPresShell *presShell = mPresContext->GetPresShell();
if (!presShell) return;
nsIFrame* containerFrame;
GetOptionsContainer(presContext, &containerFrame);
GetOptionsContainer(mPresContext, &containerFrame);
if (!containerFrame) return;
nsIFrame * childframe = nsnull;
@@ -524,12 +680,12 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer
// set up back stop colors and then ask L&F service for the real colors
nscolor color;
presContext->LookAndFeel()->
mPresContext->LookAndFeel()->
GetColor(lastItemIsSelected ?
nsILookAndFeel::eColor_WidgetSelectForeground :
nsILookAndFeel::eColor_WidgetSelectBackground, color);
nscoord onePixelInTwips = presContext->IntScaledPixelsToTwips(1);
nscoord onePixelInTwips = mPresContext->IntScaledPixelsToTwips(1);
nsRect dirty;
nscolor colors[] = {color, color, color, color};
@@ -692,8 +848,7 @@ NS_IMETHODIMP nsListControlFrame::GetAccessible(nsIAccessible** aAccessible)
if (accService) {
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(mContent);
return accService->CreateHTMLListboxAccessible(node, GetPresContext(),
aAccessible);
return accService->CreateHTMLListboxAccessible(node, mPresContext, aAccessible);
}
return NS_ERROR_FAILURE;
@@ -1011,7 +1166,7 @@ nsListControlFrame::Reflow(nsPresContext* aPresContext,
nsIContent * option = GetOptionContent(0);
if (option != nsnull) {
nsIFrame * optFrame;
nsresult result = GetPresContext()->PresShell()->
nsresult result = mPresContext->PresShell()->
GetPrimaryFrameFor(option, &optFrame);
if (NS_SUCCEEDED(result) && optFrame != nsnull) {
nsStyleContext* optStyle = optFrame->GetStyleContext();
@@ -1633,6 +1788,8 @@ nsListControlFrame::Init(nsPresContext* aPresContext,
nsStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
mPresContext = aPresContext;
NS_ADDREF(mPresContext);
nsresult result = nsHTMLScrollFrame::Init(aPresContext, aContent, aParent, aContext,
aPrevInFlow);
@@ -1890,7 +2047,7 @@ nsListControlFrame::MouseClicked(nsPresContext* aPresContext)
NS_IMETHODIMP
nsListControlFrame::OnContentReset()
{
ResetList();
ResetList(mPresContext);
return NS_OK;
}
@@ -1899,7 +2056,7 @@ nsListControlFrame::OnContentReset()
// those values as determined by the original HTML
//---------------------------------------------------------
void
nsListControlFrame::ResetList()
nsListControlFrame::ResetList(nsPresContext* aPresContext, nsVoidArray * aInxList)
{
REFLOW_DEBUG_MSG("LBX::ResetList\n");
@@ -2098,9 +2255,9 @@ nsListControlFrame::DoneAddingChildren(PRBool aIsDone)
// If so, then we can initialize;
if (mIsAllFramesHere == PR_FALSE) {
// if all the frames are now present we can initalize
if (CheckIfAllFramesHere()) {
if (CheckIfAllFramesHere() && mPresContext) {
mHasBeenInitialized = PR_TRUE;
ResetList();
ResetList(mPresContext);
}
}
}
@@ -2111,6 +2268,8 @@ nsListControlFrame::DoneAddingChildren(PRBool aIsDone)
NS_IMETHODIMP
nsListControlFrame::AddOption(nsPresContext* aPresContext, PRInt32 aIndex)
{
StopUpdateTimer();
#ifdef DO_REFLOW_DEBUG
printf("---- Id: %d nsLCF %p Added Option %d\n", mReflowId, this, aIndex);
#endif
@@ -2132,8 +2291,10 @@ nsListControlFrame::AddOption(nsPresContext* aPresContext, PRInt32 aIndex)
return NS_OK;
}
// Make sure we scroll to the selected option as needed
mNeedToReset = PR_TRUE;
nsresult rv = StartUpdateTimer(aPresContext);
if (NS_SUCCEEDED(rv) && mUpdateTimer) {
mUpdateTimer->ItemAdded(aIndex, numOptions);
}
return NS_OK;
}
@@ -2141,9 +2302,12 @@ nsListControlFrame::AddOption(nsPresContext* aPresContext, PRInt32 aIndex)
NS_IMETHODIMP
nsListControlFrame::RemoveOption(nsPresContext* aPresContext, PRInt32 aIndex)
{
// Need to reset if we're a dropdown
if (IsInDropDownMode()) {
mNeedToReset = PR_TRUE;
StopUpdateTimer();
nsresult rv = StartUpdateTimer(aPresContext);
if (NS_SUCCEEDED(rv) && mUpdateTimer) {
PRInt32 numOptions;
GetNumberOfOptions(&numOptions);
mUpdateTimer->ItemRemoved(aIndex, numOptions);
}
return NS_OK;
@@ -2243,7 +2407,7 @@ nsListControlFrame::ComboboxFinish(PRInt32 aIndex)
mComboboxFrame->RedisplaySelectedText();
}
mComboboxFrame->RollupFromList(GetPresContext());
mComboboxFrame->RollupFromList(mPresContext);
}
return NS_OK;
@@ -2279,7 +2443,7 @@ nsListControlFrame::FireOnChange()
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(NS_FORM_CHANGE);
nsIPresShell *presShell = GetPresContext()->GetPresShell();
nsIPresShell *presShell = mPresContext->GetPresShell();
if (presShell) {
rv = presShell->HandleEventWithTarget(&event, this, nsnull,
NS_EVENT_FLAG_INIT, &status);
@@ -2433,25 +2597,26 @@ nsListControlFrame::DidReflow(nsPresContext* aPresContext,
const nsHTMLReflowState* aReflowState,
nsDidReflowStatus aStatus)
{
nsresult rv;
if (PR_TRUE == IsInDropDownMode())
{
//SyncViewWithFrame();
mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW;
rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
nsresult rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
mState |= NS_FRAME_SYNC_FRAME_AND_VIEW;
SyncViewWithFrame(aPresContext);
return rv;
} else {
rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
nsresult rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
PRInt32 selectedIndex = mEndSelectionIndex;
if (selectedIndex == kNothingSelected) {
GetSelectedIndex(&selectedIndex);
}
if (!mDoneWithInitialReflow && selectedIndex != kNothingSelected) {
ScrollToIndex(selectedIndex);
mDoneWithInitialReflow = PR_TRUE;
}
return rv;
}
if (mNeedToReset) {
mNeedToReset = PR_FALSE;
ResetList();
}
return rv;
}
nsIAtom*
@@ -2545,13 +2710,13 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
nsevent->PreventBubble();
}
} else {
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
return NS_OK;
}
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
return NS_ERROR_FAILURE; // means consume event
} else {
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
return NS_OK;
}
}
@@ -2595,7 +2760,7 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
nsevent->PreventBubble();
}
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
return NS_ERROR_FAILURE;
}
@@ -2611,7 +2776,7 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
}
} else {
REFLOW_DEBUG_MSG(">>>>>> Didn't find");
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
// Notify
if (mChangesSinceDragStart) {
// reset this so that future MouseUps without a prior MouseDown
@@ -2662,13 +2827,12 @@ nsListControlFrame::FireMenuItemActiveEvent()
nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<nsIEventListenerManager> manager;
mContent->GetListenerManager(getter_AddRefs(manager));
nsPresContext* presContext = GetPresContext();
if (manager &&
NS_SUCCEEDED(manager->CreateEvent(presContext, nsnull, NS_LITERAL_STRING("Events"), getter_AddRefs(event)))) {
NS_SUCCEEDED(manager->CreateEvent(mPresContext, nsnull, NS_LITERAL_STRING("Events"), getter_AddRefs(event)))) {
event->InitEvent(NS_LITERAL_STRING("DOMMenuItemActive"), PR_TRUE, PR_TRUE);
PRBool noDefault;
presContext->EventStateManager()->DispatchNewEvent(mContent, event,
&noDefault);
mPresContext->EventStateManager()->DispatchNewEvent(mContent, event,
&noDefault);
}
}
#endif
@@ -2692,7 +2856,7 @@ nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent,
mouseEvent->GetTarget(getter_AddRefs(node));
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
nsIFrame * frame;
GetPresContext()->PresShell()->GetPrimaryFrameFor(content, &frame);
mPresContext->PresShell()->GetPrimaryFrameFor(content, &frame);
printf("Target Frame: %p this: %p\n", frame, this);
printf("-->\n");
#endif
@@ -2700,7 +2864,7 @@ nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent,
nsresult rv;
nsCOMPtr<nsIContent> content;
GetPresContext()->EventStateManager()->
mPresContext->EventStateManager()->
GetEventTargetContent(nsnull, getter_AddRefs(content));
nsCOMPtr<nsIContent> optionContent = GetOptionFromContent(content);
@@ -2756,7 +2920,7 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent)
if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, selectedIndex))) {
if (!IsInDropDownMode()) {
// Handle Like List
CaptureMouseEvents(GetPresContext(), PR_TRUE);
CaptureMouseEvents(mPresContext, PR_TRUE);
mChangesSinceDragStart = HandleListSelection(aMouseEvent, selectedIndex);
}
} else {
@@ -2771,7 +2935,7 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent)
mComboboxFrame->ShowDropDown(!isDroppedDown);
if (isDroppedDown) {
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
}
}
}
@@ -2861,8 +3025,7 @@ nsresult
nsListControlFrame::ScrollToFrame(nsIContent* aOptElement)
{
nsIScrollableView * scrollableView;
nsPresContext* presContext = GetPresContext();
GetScrollableView(presContext, &scrollableView);
GetScrollableView(mPresContext, &scrollableView);
if (scrollableView) {
// if null is passed in we scroll to 0,0
@@ -2872,7 +3035,7 @@ nsListControlFrame::ScrollToFrame(nsIContent* aOptElement)
}
// otherwise we find the content's frame and scroll to it
nsIPresShell *presShell = presContext->PresShell();
nsIPresShell *presShell = mPresContext->PresShell();
nsIFrame * childframe;
nsresult result;
if (aOptElement) {
@@ -2898,7 +3061,7 @@ nsListControlFrame::ScrollToFrame(nsIContent* aOptElement)
nsRect fRect = childframe->GetRect();
nsPoint pnt;
nsIView * view;
childframe->GetOffsetFromView(presContext, pnt, &view);
childframe->GetOffsetFromView(mPresContext, pnt, &view);
// This change for 33421 (remove this comment later)
@@ -3306,7 +3469,7 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
// because this isn't needed for Gfx
if (IsInDropDownMode() == PR_TRUE) {
// Don't flush anything but reflows lest it destroy us
GetPresContext()->PresShell()->
mPresContext->PresShell()->
GetDocument()->FlushPendingNotifications(Flush_OnlyReflow);
}
REFLOW_DEBUG_MSG2(" After: %d\n", newIndex);
@@ -3376,3 +3539,40 @@ IGNORE_EVENT(DragMove)
#undef FORWARD_EVENT
#undef IGNORE_EVENT
/*=============== Timer Related Code ======================*/
nsresult
nsListControlFrame::StartUpdateTimer(nsPresContext * aPresContext)
{
if (mUpdateTimer == nsnull) {
nsresult result = NS_NewUpdateTimer(&mUpdateTimer);
if (NS_FAILED(result))
return result;
mUpdateTimer->Init(this, 0); // delay "0"
}
if (mUpdateTimer != nsnull) {
return mUpdateTimer->Start(aPresContext);
}
return NS_ERROR_FAILURE;
}
void
nsListControlFrame::StopUpdateTimer()
{
if (mUpdateTimer != nsnull) {
mUpdateTimer->Stop();
}
}
void
nsListControlFrame::ItemsHaveBeenRemoved(nsPresContext * aPresContext)
{
// Only adjust things if it is a combobox
// removing items on a listbox should effect anything
if (IsInDropDownMode()) {
ResetList(aPresContext);
}
}

View File

@@ -67,6 +67,7 @@ class nsPresContext;
class nsVoidArray;
class nsIScrollableView;
class nsSelectUpdateTimer;
class nsVoidArray;
class nsListEventListener;
@@ -82,6 +83,7 @@ class nsListControlFrame : public nsHTMLScrollFrame,
{
public:
friend nsresult NS_NewListControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
friend class nsSelectUpdateTimer;
// nsISupports
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
@@ -231,7 +233,7 @@ protected:
PRBool IsClickingInCombobox(nsIDOMEvent* aMouseEvent);
void AdjustIndexForDisabledOpt(PRInt32 aStartIndex, PRInt32 &anNewIndex,
PRInt32 aNumOptions, PRInt32 aDoAdjustInc, PRInt32 aDoAdjustIncNext);
virtual void ResetList();
virtual void ResetList(nsPresContext* aPresContext, nsVoidArray * aInxList = nsnull);
nsListControlFrame(nsIPresShell* aShell, nsIDocument* aDocument);
virtual ~nsListControlFrame();
@@ -267,6 +269,11 @@ protected:
PRBool HandleListSelection(nsIDOMEvent * aDOMEvent, PRInt32 selectedIndex);
void InitSelectionRange(PRInt32 aClickedIndex);
// Timer Methods
nsresult StartUpdateTimer(nsPresContext * aPresContext);
void StopUpdateTimer();
void ItemsHaveBeenRemoved(nsPresContext * aPresContext);
// Data Members
PRInt32 mStartSelectionIndex;
PRInt32 mEndSelectionIndex;
@@ -281,15 +288,20 @@ protected:
PRBool mIsAllContentHere;
PRPackedBool mIsAllFramesHere;
PRPackedBool mHasBeenInitialized;
PRPackedBool mNeedToReset;
PRPackedBool mDoneWithInitialReflow;
PRPackedBool mOverrideReflowOpt;
nsPresContext* mPresContext; // XXX: Remove the need to cache the pres context.
nsRefPtr<nsListEventListener> mEventListener;
PRInt16 mPassId;
nscoord mCachedDesiredMEW;
// Update timer
nsSelectUpdateTimer * mUpdateTimer;
nsIFrame* mDummyFrame;
//Resize Reflow OpitmizationSize;

View File

@@ -90,6 +90,9 @@
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMKeyListener.h"
// Timer Includes
#include "nsITimer.h"
// Constants
const nscoord kMaxDropDownRows = 20; // This matches the setting for 4.x browsers
const PRInt32 kDefaultMultiselectHeight = 4; // This is compatible with 4.x browsers
@@ -279,21 +282,169 @@ if (aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE) { \
//-- Done with macros
//------------------------------------------------------
//---------------------------------------------------
//-- Update Timer Stuff
//---------------------------------------------------
class nsSelectUpdateTimer : public nsITimerCallback
{
public:
NS_DECL_ISUPPORTS
nsSelectUpdateTimer()
: mPresContext(nsnull), mDelay(0), mHasBeenNotified(PR_FALSE),
mItemsAdded(PR_FALSE), mItemsRemoved(PR_FALSE), mItemsInxSet(PR_FALSE)
{
}
virtual ~nsSelectUpdateTimer();
NS_DECL_NSITIMERCALLBACK
// Additional Methods
nsresult Start(nsPresContext *aPresContext)
{
mPresContext = aPresContext;
nsresult result = NS_OK;
if (!mTimer) {
mTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
if (NS_FAILED(result))
return result;
}
result = mTimer->InitWithCallback(this, mDelay, nsITimer::TYPE_ONE_SHOT);
if (mHasBeenNotified) {
mItemsAdded = PR_FALSE;
mItemsRemoved = PR_FALSE;
mItemsInxSet = PR_FALSE;
mHasBeenNotified = PR_FALSE;
mInxArray.Clear();
}
return result;
}
void Init(nsListControlFrame *aList, PRUint32 aDelay) { mListControl = aList; mDelay = aDelay; }
void Stop() { if (mTimer) mTimer->Cancel(); }
void AdjustIndexes(PRBool aInserted, PRInt32 aInx)
{
// remove the index from the list
if (!aInserted) {
PRInt32 inx = (PRInt32)mInxArray.IndexOf((void*)aInx);
if (inx > -1) {
mInxArray.RemoveElementAt(inx);
}
}
PRInt32 count = mInxArray.Count();
for (PRInt32 i=0;i<count;i++) {
PRInt32 inx = NS_PTR_TO_INT32(mInxArray[i]);
if (inx > aInx) {
mInxArray.ReplaceElementAt((void*)(inx+(aInserted?1:-1)), i);
}
}
}
void ItemAdded(PRInt32 aInx, PRInt32 aNumItems)
{
mItemsAdded = PR_TRUE;
if (mInxArray.Count() > 0 && aInx <= aNumItems-1) {
AdjustIndexes(PR_TRUE, aInx);
}
}
void ItemRemoved(PRInt32 aInx, PRInt32 aNumItems)
{
mItemsRemoved = PR_TRUE;
if (mInxArray.Count() > 0 && aInx <= aNumItems) {
AdjustIndexes(PR_FALSE, aInx);
}
}
void ItemIndexSet(PRInt32 aInx)
{
mItemsInxSet = PR_TRUE;
mInxArray.AppendElement((void*)aInx);
}
PRPackedBool HasBeenNotified() { return mHasBeenNotified; }
private:
nsListControlFrame * mListControl;
nsCOMPtr<nsITimer> mTimer;
nsPresContext* mPresContext;
PRUint32 mDelay;
PRPackedBool mHasBeenNotified;
PRPackedBool mItemsAdded;
PRPackedBool mItemsRemoved;
PRPackedBool mItemsInxSet;
nsVoidArray mInxArray;
};
NS_IMPL_ADDREF(nsSelectUpdateTimer)
NS_IMPL_RELEASE(nsSelectUpdateTimer)
NS_IMPL_QUERY_INTERFACE1(nsSelectUpdateTimer, nsITimerCallback)
nsresult NS_NewUpdateTimer(nsSelectUpdateTimer **aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
*aResult = (nsSelectUpdateTimer*) new nsSelectUpdateTimer;
if (!aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
// nsITimerCallback
NS_IMETHODIMP nsSelectUpdateTimer::Notify(nsITimer *timer)
{
if (mPresContext && mListControl && !mHasBeenNotified) {
mHasBeenNotified = PR_TRUE;
if (mItemsAdded || mItemsInxSet) {
mListControl->ResetList(mPresContext, &mInxArray);
} else {
mListControl->ItemsHaveBeenRemoved(mPresContext);
}
}
return NS_OK;
}
nsSelectUpdateTimer::~nsSelectUpdateTimer()
{
if (mTimer) {
mTimer->Cancel();
}
}
//---------------------------------------------------
//-- DONE: Update Timer Stuff
//---------------------------------------------------
//---------------------------------------------------------
nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
nsIDocument* aDocument)
: nsHTMLScrollFrame(aShell, PR_FALSE)
{
mComboboxFrame = nsnull;
mChangesSinceDragStart = PR_FALSE;
mButtonDown = PR_FALSE;
mMaxWidth = 0;
mMaxHeight = 0;
mPresContext = nsnull;
mIsAllContentHere = PR_FALSE;
mIsAllFramesHere = PR_FALSE;
mHasBeenInitialized = PR_FALSE;
mNeedToReset = PR_TRUE;
mDoneWithInitialReflow = PR_FALSE;
mCacheSize.width = -1;
mCacheSize.height = -1;
@@ -306,6 +457,7 @@ nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
mOverrideReflowOpt = PR_FALSE;
mPassId = 0;
mUpdateTimer = nsnull;
mDummyFrame = nsnull;
REFLOW_COUNTER_INIT()
@@ -315,8 +467,13 @@ nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
nsListControlFrame::~nsListControlFrame()
{
REFLOW_COUNTER_DUMP("nsLCF");
if (mUpdateTimer != nsnull) {
StopUpdateTimer();
NS_RELEASE(mUpdateTimer);
}
mComboboxFrame = nsnull;
NS_IF_RELEASE(mPresContext);
}
// for Bug 47302 (remove this comment later)
@@ -426,16 +583,15 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer
focusedIndex = mEndSelectionIndex;
}
nsPresContext* presContext = GetPresContext();
nsIScrollableView * scrollableView;
GetScrollableView(presContext, &scrollableView);
GetScrollableView(mPresContext, &scrollableView);
if (!scrollableView) return;
nsIPresShell *presShell = presContext->GetPresShell();
nsIPresShell *presShell = mPresContext->GetPresShell();
if (!presShell) return;
nsIFrame* containerFrame;
GetOptionsContainer(presContext, &containerFrame);
GetOptionsContainer(mPresContext, &containerFrame);
if (!containerFrame) return;
nsIFrame * childframe = nsnull;
@@ -524,12 +680,12 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer
// set up back stop colors and then ask L&F service for the real colors
nscolor color;
presContext->LookAndFeel()->
mPresContext->LookAndFeel()->
GetColor(lastItemIsSelected ?
nsILookAndFeel::eColor_WidgetSelectForeground :
nsILookAndFeel::eColor_WidgetSelectBackground, color);
nscoord onePixelInTwips = presContext->IntScaledPixelsToTwips(1);
nscoord onePixelInTwips = mPresContext->IntScaledPixelsToTwips(1);
nsRect dirty;
nscolor colors[] = {color, color, color, color};
@@ -692,8 +848,7 @@ NS_IMETHODIMP nsListControlFrame::GetAccessible(nsIAccessible** aAccessible)
if (accService) {
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(mContent);
return accService->CreateHTMLListboxAccessible(node, GetPresContext(),
aAccessible);
return accService->CreateHTMLListboxAccessible(node, mPresContext, aAccessible);
}
return NS_ERROR_FAILURE;
@@ -1011,7 +1166,7 @@ nsListControlFrame::Reflow(nsPresContext* aPresContext,
nsIContent * option = GetOptionContent(0);
if (option != nsnull) {
nsIFrame * optFrame;
nsresult result = GetPresContext()->PresShell()->
nsresult result = mPresContext->PresShell()->
GetPrimaryFrameFor(option, &optFrame);
if (NS_SUCCEEDED(result) && optFrame != nsnull) {
nsStyleContext* optStyle = optFrame->GetStyleContext();
@@ -1633,6 +1788,8 @@ nsListControlFrame::Init(nsPresContext* aPresContext,
nsStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
mPresContext = aPresContext;
NS_ADDREF(mPresContext);
nsresult result = nsHTMLScrollFrame::Init(aPresContext, aContent, aParent, aContext,
aPrevInFlow);
@@ -1890,7 +2047,7 @@ nsListControlFrame::MouseClicked(nsPresContext* aPresContext)
NS_IMETHODIMP
nsListControlFrame::OnContentReset()
{
ResetList();
ResetList(mPresContext);
return NS_OK;
}
@@ -1899,7 +2056,7 @@ nsListControlFrame::OnContentReset()
// those values as determined by the original HTML
//---------------------------------------------------------
void
nsListControlFrame::ResetList()
nsListControlFrame::ResetList(nsPresContext* aPresContext, nsVoidArray * aInxList)
{
REFLOW_DEBUG_MSG("LBX::ResetList\n");
@@ -2098,9 +2255,9 @@ nsListControlFrame::DoneAddingChildren(PRBool aIsDone)
// If so, then we can initialize;
if (mIsAllFramesHere == PR_FALSE) {
// if all the frames are now present we can initalize
if (CheckIfAllFramesHere()) {
if (CheckIfAllFramesHere() && mPresContext) {
mHasBeenInitialized = PR_TRUE;
ResetList();
ResetList(mPresContext);
}
}
}
@@ -2111,6 +2268,8 @@ nsListControlFrame::DoneAddingChildren(PRBool aIsDone)
NS_IMETHODIMP
nsListControlFrame::AddOption(nsPresContext* aPresContext, PRInt32 aIndex)
{
StopUpdateTimer();
#ifdef DO_REFLOW_DEBUG
printf("---- Id: %d nsLCF %p Added Option %d\n", mReflowId, this, aIndex);
#endif
@@ -2132,8 +2291,10 @@ nsListControlFrame::AddOption(nsPresContext* aPresContext, PRInt32 aIndex)
return NS_OK;
}
// Make sure we scroll to the selected option as needed
mNeedToReset = PR_TRUE;
nsresult rv = StartUpdateTimer(aPresContext);
if (NS_SUCCEEDED(rv) && mUpdateTimer) {
mUpdateTimer->ItemAdded(aIndex, numOptions);
}
return NS_OK;
}
@@ -2141,9 +2302,12 @@ nsListControlFrame::AddOption(nsPresContext* aPresContext, PRInt32 aIndex)
NS_IMETHODIMP
nsListControlFrame::RemoveOption(nsPresContext* aPresContext, PRInt32 aIndex)
{
// Need to reset if we're a dropdown
if (IsInDropDownMode()) {
mNeedToReset = PR_TRUE;
StopUpdateTimer();
nsresult rv = StartUpdateTimer(aPresContext);
if (NS_SUCCEEDED(rv) && mUpdateTimer) {
PRInt32 numOptions;
GetNumberOfOptions(&numOptions);
mUpdateTimer->ItemRemoved(aIndex, numOptions);
}
return NS_OK;
@@ -2243,7 +2407,7 @@ nsListControlFrame::ComboboxFinish(PRInt32 aIndex)
mComboboxFrame->RedisplaySelectedText();
}
mComboboxFrame->RollupFromList(GetPresContext());
mComboboxFrame->RollupFromList(mPresContext);
}
return NS_OK;
@@ -2279,7 +2443,7 @@ nsListControlFrame::FireOnChange()
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(NS_FORM_CHANGE);
nsIPresShell *presShell = GetPresContext()->GetPresShell();
nsIPresShell *presShell = mPresContext->GetPresShell();
if (presShell) {
rv = presShell->HandleEventWithTarget(&event, this, nsnull,
NS_EVENT_FLAG_INIT, &status);
@@ -2433,25 +2597,26 @@ nsListControlFrame::DidReflow(nsPresContext* aPresContext,
const nsHTMLReflowState* aReflowState,
nsDidReflowStatus aStatus)
{
nsresult rv;
if (PR_TRUE == IsInDropDownMode())
{
//SyncViewWithFrame();
mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW;
rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
nsresult rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
mState |= NS_FRAME_SYNC_FRAME_AND_VIEW;
SyncViewWithFrame(aPresContext);
return rv;
} else {
rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
nsresult rv = nsHTMLScrollFrame::DidReflow(aPresContext, aReflowState, aStatus);
PRInt32 selectedIndex = mEndSelectionIndex;
if (selectedIndex == kNothingSelected) {
GetSelectedIndex(&selectedIndex);
}
if (!mDoneWithInitialReflow && selectedIndex != kNothingSelected) {
ScrollToIndex(selectedIndex);
mDoneWithInitialReflow = PR_TRUE;
}
return rv;
}
if (mNeedToReset) {
mNeedToReset = PR_FALSE;
ResetList();
}
return rv;
}
nsIAtom*
@@ -2545,13 +2710,13 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
nsevent->PreventBubble();
}
} else {
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
return NS_OK;
}
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
return NS_ERROR_FAILURE; // means consume event
} else {
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
return NS_OK;
}
}
@@ -2595,7 +2760,7 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
nsevent->PreventBubble();
}
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
return NS_ERROR_FAILURE;
}
@@ -2611,7 +2776,7 @@ nsListControlFrame::MouseUp(nsIDOMEvent* aMouseEvent)
}
} else {
REFLOW_DEBUG_MSG(">>>>>> Didn't find");
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
// Notify
if (mChangesSinceDragStart) {
// reset this so that future MouseUps without a prior MouseDown
@@ -2662,13 +2827,12 @@ nsListControlFrame::FireMenuItemActiveEvent()
nsCOMPtr<nsIDOMEvent> event;
nsCOMPtr<nsIEventListenerManager> manager;
mContent->GetListenerManager(getter_AddRefs(manager));
nsPresContext* presContext = GetPresContext();
if (manager &&
NS_SUCCEEDED(manager->CreateEvent(presContext, nsnull, NS_LITERAL_STRING("Events"), getter_AddRefs(event)))) {
NS_SUCCEEDED(manager->CreateEvent(mPresContext, nsnull, NS_LITERAL_STRING("Events"), getter_AddRefs(event)))) {
event->InitEvent(NS_LITERAL_STRING("DOMMenuItemActive"), PR_TRUE, PR_TRUE);
PRBool noDefault;
presContext->EventStateManager()->DispatchNewEvent(mContent, event,
&noDefault);
mPresContext->EventStateManager()->DispatchNewEvent(mContent, event,
&noDefault);
}
}
#endif
@@ -2692,7 +2856,7 @@ nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent,
mouseEvent->GetTarget(getter_AddRefs(node));
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
nsIFrame * frame;
GetPresContext()->PresShell()->GetPrimaryFrameFor(content, &frame);
mPresContext->PresShell()->GetPrimaryFrameFor(content, &frame);
printf("Target Frame: %p this: %p\n", frame, this);
printf("-->\n");
#endif
@@ -2700,7 +2864,7 @@ nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent,
nsresult rv;
nsCOMPtr<nsIContent> content;
GetPresContext()->EventStateManager()->
mPresContext->EventStateManager()->
GetEventTargetContent(nsnull, getter_AddRefs(content));
nsCOMPtr<nsIContent> optionContent = GetOptionFromContent(content);
@@ -2756,7 +2920,7 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent)
if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, selectedIndex))) {
if (!IsInDropDownMode()) {
// Handle Like List
CaptureMouseEvents(GetPresContext(), PR_TRUE);
CaptureMouseEvents(mPresContext, PR_TRUE);
mChangesSinceDragStart = HandleListSelection(aMouseEvent, selectedIndex);
}
} else {
@@ -2771,7 +2935,7 @@ nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent)
mComboboxFrame->ShowDropDown(!isDroppedDown);
if (isDroppedDown) {
CaptureMouseEvents(GetPresContext(), PR_FALSE);
CaptureMouseEvents(mPresContext, PR_FALSE);
}
}
}
@@ -2861,8 +3025,7 @@ nsresult
nsListControlFrame::ScrollToFrame(nsIContent* aOptElement)
{
nsIScrollableView * scrollableView;
nsPresContext* presContext = GetPresContext();
GetScrollableView(presContext, &scrollableView);
GetScrollableView(mPresContext, &scrollableView);
if (scrollableView) {
// if null is passed in we scroll to 0,0
@@ -2872,7 +3035,7 @@ nsListControlFrame::ScrollToFrame(nsIContent* aOptElement)
}
// otherwise we find the content's frame and scroll to it
nsIPresShell *presShell = presContext->PresShell();
nsIPresShell *presShell = mPresContext->PresShell();
nsIFrame * childframe;
nsresult result;
if (aOptElement) {
@@ -2898,7 +3061,7 @@ nsListControlFrame::ScrollToFrame(nsIContent* aOptElement)
nsRect fRect = childframe->GetRect();
nsPoint pnt;
nsIView * view;
childframe->GetOffsetFromView(presContext, pnt, &view);
childframe->GetOffsetFromView(mPresContext, pnt, &view);
// This change for 33421 (remove this comment later)
@@ -3306,7 +3469,7 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
// because this isn't needed for Gfx
if (IsInDropDownMode() == PR_TRUE) {
// Don't flush anything but reflows lest it destroy us
GetPresContext()->PresShell()->
mPresContext->PresShell()->
GetDocument()->FlushPendingNotifications(Flush_OnlyReflow);
}
REFLOW_DEBUG_MSG2(" After: %d\n", newIndex);
@@ -3376,3 +3539,40 @@ IGNORE_EVENT(DragMove)
#undef FORWARD_EVENT
#undef IGNORE_EVENT
/*=============== Timer Related Code ======================*/
nsresult
nsListControlFrame::StartUpdateTimer(nsPresContext * aPresContext)
{
if (mUpdateTimer == nsnull) {
nsresult result = NS_NewUpdateTimer(&mUpdateTimer);
if (NS_FAILED(result))
return result;
mUpdateTimer->Init(this, 0); // delay "0"
}
if (mUpdateTimer != nsnull) {
return mUpdateTimer->Start(aPresContext);
}
return NS_ERROR_FAILURE;
}
void
nsListControlFrame::StopUpdateTimer()
{
if (mUpdateTimer != nsnull) {
mUpdateTimer->Stop();
}
}
void
nsListControlFrame::ItemsHaveBeenRemoved(nsPresContext * aPresContext)
{
// Only adjust things if it is a combobox
// removing items on a listbox should effect anything
if (IsInDropDownMode()) {
ResetList(aPresContext);
}
}

View File

@@ -67,6 +67,7 @@ class nsPresContext;
class nsVoidArray;
class nsIScrollableView;
class nsSelectUpdateTimer;
class nsVoidArray;
class nsListEventListener;
@@ -82,6 +83,7 @@ class nsListControlFrame : public nsHTMLScrollFrame,
{
public:
friend nsresult NS_NewListControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
friend class nsSelectUpdateTimer;
// nsISupports
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
@@ -231,7 +233,7 @@ protected:
PRBool IsClickingInCombobox(nsIDOMEvent* aMouseEvent);
void AdjustIndexForDisabledOpt(PRInt32 aStartIndex, PRInt32 &anNewIndex,
PRInt32 aNumOptions, PRInt32 aDoAdjustInc, PRInt32 aDoAdjustIncNext);
virtual void ResetList();
virtual void ResetList(nsPresContext* aPresContext, nsVoidArray * aInxList = nsnull);
nsListControlFrame(nsIPresShell* aShell, nsIDocument* aDocument);
virtual ~nsListControlFrame();
@@ -267,6 +269,11 @@ protected:
PRBool HandleListSelection(nsIDOMEvent * aDOMEvent, PRInt32 selectedIndex);
void InitSelectionRange(PRInt32 aClickedIndex);
// Timer Methods
nsresult StartUpdateTimer(nsPresContext * aPresContext);
void StopUpdateTimer();
void ItemsHaveBeenRemoved(nsPresContext * aPresContext);
// Data Members
PRInt32 mStartSelectionIndex;
PRInt32 mEndSelectionIndex;
@@ -281,15 +288,20 @@ protected:
PRBool mIsAllContentHere;
PRPackedBool mIsAllFramesHere;
PRPackedBool mHasBeenInitialized;
PRPackedBool mNeedToReset;
PRPackedBool mDoneWithInitialReflow;
PRPackedBool mOverrideReflowOpt;
nsPresContext* mPresContext; // XXX: Remove the need to cache the pres context.
nsRefPtr<nsListEventListener> mEventListener;
PRInt16 mPassId;
nscoord mCachedDesiredMEW;
// Update timer
nsSelectUpdateTimer * mUpdateTimer;
nsIFrame* mDummyFrame;
//Resize Reflow OpitmizationSize;