Index: layout/base/nsPresContext.cpp =================================================================== RCS file: /cvsroot/mozilla/layout/base/nsPresContext.cpp,v retrieving revision 3.288.12.5 diff -d -u -p -r3.288.12.5 nsPresContext.cpp --- layout/base/nsPresContext.cpp 17 May 2006 07:56:35 -0000 3.288.12.5 +++ layout/base/nsPresContext.cpp 19 Sep 2008 16:33:31 -0000 @@ -73,6 +73,9 @@ #include "nsIDOMDocument.h" #include "nsAutoPtr.h" #include "nsEventStateManager.h" +#include "nsIEventQueue.h" +#include "nsIEventQueueService.h" + #ifdef IBMBIDI #include "nsBidiPresUtils.h" #endif // IBMBIDI @@ -267,6 +270,7 @@ nsPresContext::~nsPresContext() NS_IF_RELEASE(mDeviceContext); NS_IF_RELEASE(mLookAndFeel); NS_IF_RELEASE(mLangGroup); + NS_IF_RELEASE(mEventQueueService); } NS_IMPL_ISUPPORTS2(nsPresContext, nsPresContext, nsIObserver) @@ -285,6 +289,17 @@ static const char* const kGenericFont[] ".fantasy." }; +// Set to true when LookAndFeelChanged needs to be called. This is used +// because the look and feel is a service, so there's no need to notify it from +// more than one prescontext. +static PRBool sLookAndFeelChanged; + +// Set to true when ThemeChanged needs to be called on mTheme. This is used +// because mTheme is a service, so there's no need to notify it from more than +// one prescontext. +static PRBool sThemeChanged; + + void nsPresContext::GetFontPreferences() { @@ -716,6 +731,9 @@ nsPresContext::Init(nsIDeviceContext* aD this); #endif + rv = CallGetService(NS_EVENTQUEUESERVICE_CONTRACTID, &mEventQueueService); + NS_ENSURE_SUCCESS(rv, rv); + // Initialize our state from the user preferences GetUserPreferences(); @@ -1197,33 +1215,126 @@ nsPresContext::GetTheme() void nsPresContext::ThemeChanged() { + if (!mPendingThemeChanged) { + sLookAndFeelChanged = PR_TRUE; + sThemeChanged = PR_TRUE; + + nsCOMPtr eventQ; + mEventQueueService-> + GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, + getter_AddRefs(eventQ)); + if (!eventQ) { + return; + } + + PLEvent* evt = new PLEvent(); + if (!evt) { + return; + } + + PL_InitEvent(evt, this, nsPresContext::ThemeChangedInternal, + nsPresContext::DestroyThemeChangeEvt); + + // After this point, event destruction will release |this| + NS_ADDREF_THIS(); + + nsresult rv = eventQ->PostEvent(evt); + if (NS_FAILED(rv)) { + PL_DestroyEvent(evt); + } else { + mPendingThemeChanged = PR_TRUE; + } + } +} + +void* PR_CALLBACK +nsPresContext::ThemeChangedInternal(PLEvent *aEvent) +{ + nsPresContext* pc = NS_STATIC_CAST(nsPresContext*, aEvent->owner); + + pc->mPendingThemeChanged = PR_FALSE; + // Tell the theme that it changed, so it can flush any handles to stale theme // data. - if (mTheme) - mTheme->ThemeChanged(); + if (pc->mTheme && sThemeChanged) { + pc->mTheme->ThemeChanged(); + sThemeChanged = PR_FALSE; + } // Clear all cached nsILookAndFeel colors. - if (mLookAndFeel) - mLookAndFeel->LookAndFeelChanged(); + if (pc->mLookAndFeel && sLookAndFeelChanged) { + pc->mLookAndFeel->LookAndFeelChanged(); + sLookAndFeelChanged = PR_FALSE; + } // We have to clear style data because the assumption of style rule // immutability has been violated since any style rule that uses // system colors or fonts (and probably -moz-appearance as well) has // changed. - nsPresContext::ClearStyleDataAndReflow(); + pc->ClearStyleDataAndReflow(); + + return nsnull; +} + + +void PR_CALLBACK +nsPresContext::DestroyThemeChangeEvt(PLEvent* aEvent) +{ + nsPresContext* pc = NS_STATIC_CAST(nsPresContext*, aEvent->owner); + NS_RELEASE(pc); + delete aEvent; } void nsPresContext::SysColorChanged() { - if (mLookAndFeel) { + if (!mPendingSysColorChanged) { + sLookAndFeelChanged = PR_TRUE; + + nsCOMPtr eventQ; + mEventQueueService-> + GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE, + getter_AddRefs(eventQ)); + if (!eventQ) { + return; + } + + PLEvent* evt = new PLEvent(); + if (!evt) { + return; + } + + PL_InitEvent(evt, this, nsPresContext::SysColorChangedInternal, + nsPresContext::DestroySysColorChangeEvt); + + // After this point, event destruction will release |this| + NS_ADDREF_THIS(); + + nsresult rv = eventQ->PostEvent(evt); + if (NS_FAILED(rv)) { + PL_DestroyEvent(evt); + } else { + mPendingSysColorChanged = PR_TRUE; + } + } +} + +void* PR_CALLBACK +nsPresContext::SysColorChangedInternal(PLEvent *aEvent) +{ + nsPresContext* pc = NS_STATIC_CAST(nsPresContext*, aEvent->owner); + + pc->mPendingSysColorChanged = PR_FALSE; + + if (pc->mLookAndFeel && sLookAndFeelChanged) { // Don't use the cached values for the system colors - mLookAndFeel->LookAndFeelChanged(); + pc->mLookAndFeel->LookAndFeelChanged(); + sLookAndFeelChanged = PR_FALSE; } - + // Reset default background and foreground colors for the document since // they may be using system colors - GetDocumentColorPreferences(); + pc->GetDocumentColorPreferences(); // Clear out all of the style data since it may contain RGB values // which originated from system colors. @@ -1239,7 +1350,17 @@ nsPresContext::SysColorChanged() // data without reflowing/updating views will lead to incorrect change hints // later, because when generating change hints, any style structs which have // been cleared and not reread are assumed to not be used at all. - ClearStyleDataAndReflow(); + pc->ClearStyleDataAndReflow(); + + return nsnull; +} + +void PR_CALLBACK +nsPresContext::DestroySysColorChangeEvt(PLEvent* aEvent) +{ + nsPresContext* pc = NS_STATIC_CAST(nsPresContext*, aEvent->owner); + NS_RELEASE(pc); + delete aEvent; } void Index: layout/base/nsPresContext.h =================================================================== RCS file: /cvsroot/mozilla/layout/base/nsPresContext.h,v retrieving revision 3.150.4.3 diff -d -u -p -r3.150.4.3 nsPresContext.h --- layout/base/nsPresContext.h 29 Aug 2007 23:07:47 -0000 3.150.4.3 +++ layout/base/nsPresContext.h 19 Sep 2008 16:33:31 -0000 @@ -56,6 +56,7 @@ #include "nsCRT.h" #include "nsIPrintSettings.h" #include "nsPropertyTable.h" +#include "plevent.h" #ifdef IBMBIDI class nsBidiPresUtils; #endif // IBMBIDI @@ -76,6 +77,7 @@ class nsIAtom; class nsIEventStateManager; class nsIURI; class nsILookAndFeel; +class nsIEventQueueService; class nsICSSPseudoComparator; class nsIAtom; struct nsStyleStruct; @@ -630,6 +632,14 @@ public: PRBool IsChrome(); protected: + static NS_HIDDEN_(void*) PR_CALLBACK ThemeChangedInternal(PLEvent* aEvent); + static NS_HIDDEN_(void*) PR_CALLBACK SysColorChangedInternal(PLEvent* aEvent); + static NS_HIDDEN_(void) PR_CALLBACK DestroyThemeChangeEvt(PLEvent* aEvent); + static NS_HIDDEN_(void) PR_CALLBACK DestroySysColorChangeEvt(PLEvent* aEvent); + + friend void* PR_CALLBACK ThemeChangedInternal(PLEvent* aEvent); + friend void* PR_CALLBACK SysColorChangedInternal(PLEvent* aEvent); + NS_HIDDEN_(void) SetImgAnimations(nsIContent *aParent, PRUint16 aMode); NS_HIDDEN_(void) GetDocumentColorPreferences(); @@ -657,6 +667,7 @@ protected: // from gfx back to layout. nsIEventStateManager* mEventManager; // [STRONG] nsILookAndFeel* mLookAndFeel; // [STRONG] + nsIEventQueueService *mEventQueueService; // [STRONG] nsIAtom* mMedium; // initialized by subclass ctors; // weak pointer to static atom @@ -727,6 +738,8 @@ protected: unsigned mCanPaginatedScroll : 1; unsigned mDoScaledTwips : 1; unsigned mEnableJapaneseTransform : 1; + unsigned mPendingSysColorChanged : 1; + unsigned mPendingThemeChanged : 1; #ifdef IBMBIDI unsigned mIsVisual : 1; unsigned mIsBidiSystem : 1;