From 6856aa06f04805aa1f809d32449495aec704f411 Mon Sep 17 00:00:00 2001 From: "michael.lowe%bigfoot.com" Date: Fri, 21 Jan 2000 21:56:09 +0000 Subject: [PATCH] Repeating, prioritised timer implementation for Windows and Gtk (bug 22979). author={Win32=michael.lowe@bigfoot.com, Gtk=alex@cendio.se}, r={kmcclusk,rods,sfraser,et al} a=brendan git-svn-id: svn://10.0.0.236/trunk@58358 18797224-902f-48f8-a5cc-f745e15eee43 --- .../chrome/src/nsChromeProtocolHandler.cpp | 4 +- .../html/document/src/nsHTMLContentSink.cpp | 4 +- .../xul/content/src/nsXULPopupListener.cpp | 2 +- mozilla/docshell/base/nsWebShell.cpp | 4 +- mozilla/dom/src/base/nsGlobalWindow.cpp | 4 +- .../tests/components/xpctest_echo.cpp | 4 +- mozilla/layout/base/nsCaret.cpp | 5 +- mozilla/layout/base/src/nsCaret.cpp | 5 +- mozilla/layout/base/src/nsRangeList.cpp | 2 +- mozilla/layout/generic/nsObjectFrame.cpp | 8 +- mozilla/layout/generic/nsTextFrame.cpp | 8 +- .../layout/html/base/src/nsObjectFrame.cpp | 8 +- mozilla/layout/html/base/src/nsTextFrame.cpp | 8 +- .../html/document/src/nsHTMLContentSink.cpp | 4 +- mozilla/layout/xul/base/src/nsMenuFrame.cpp | 26 +- mozilla/layout/xul/base/src/nsMenuFrame.h | 2 +- .../xul/base/src/nsProgressMeterFrame.cpp | 8 +- .../layout/xul/base/src/nsRepeatService.cpp | 2 +- mozilla/layout/xul/base/src/nsRepeatService.h | 2 +- .../xul/base/src/nsScrollbarButtonFrame.cpp | 2 +- .../xul/base/src/nsScrollbarButtonFrame.h | 2 +- mozilla/layout/xul/base/src/nsSliderFrame.cpp | 2 +- mozilla/layout/xul/base/src/nsSliderFrame.h | 2 +- .../chrome/src/nsChromeProtocolHandler.cpp | 4 +- .../rdf/content/src/nsXULPopupListener.cpp | 2 +- mozilla/view/src/nsScrollPortView.h | 2 +- mozilla/view/src/nsScrollingView.cpp | 4 +- mozilla/view/src/nsScrollingView.h | 2 +- mozilla/webshell/src/nsWebShell.cpp | 4 +- .../webshell/tests/viewer/nsSetupRegistry.cpp | 6 + mozilla/webshell/tests/viewer/nsThrobber.cpp | 4 +- mozilla/webshell/tests/viewer/nsWinMain.cpp | 44 +- mozilla/widget/public/nsILookAndFeel.h | 3 +- mozilla/widget/public/nsWidgetsCID.h | 10 + mozilla/widget/src/beos/nsLookAndFeel.cpp | 3 + mozilla/widget/src/build/makefile.win | 1 + .../widget/src/build/nsWinWidgetFactory.cpp | 16 + mozilla/widget/src/gtk/nsLookAndFeel.cpp | 3 + mozilla/widget/src/gtk/nsWindow.cpp | 2 +- mozilla/widget/src/gtk/nsWindow.h | 2 +- mozilla/widget/src/mac/nsLookAndFeel.cpp | 3 + mozilla/widget/src/motif/nsLookAndFeel.cpp | 3 + mozilla/widget/src/os2/nsLookAndFeel.cpp | 3 + mozilla/widget/src/photon/nsLookAndFeel.cpp | 3 + mozilla/widget/src/qt/nsLookAndFeel.cpp | 3 + mozilla/widget/src/windows/nsAppShell.cpp | 69 ++- mozilla/widget/src/windows/nsLookAndFeel.cpp | 35 ++ mozilla/widget/src/windows/nsWindow.cpp | 24 +- mozilla/widget/src/xlib/nsLookAndFeel.cpp | 3 + mozilla/widget/timer/public/makefile.win | 1 + mozilla/widget/timer/public/nsITimer.h | 73 ++- .../widget/timer/public/nsITimerCallback.h | 2 +- mozilla/widget/timer/src/beos/nsTimer.cpp | 31 +- mozilla/widget/timer/src/mac/nsTimer.cpp | 29 +- mozilla/widget/timer/src/os2/nsTimerOS2.cpp | 6 +- mozilla/widget/timer/src/os2/nsTimerOS2.h | 16 +- mozilla/widget/timer/src/photon/nsTimer.cpp | 25 +- mozilla/widget/timer/src/rhapsody/nsTimer.cpp | 32 +- .../widget/timer/src/unix/gtk/nsTimerGtk.cpp | 134 ++--- .../widget/timer/src/unix/gtk/nsTimerGtk.h | 29 +- .../timer/src/unix/motif/nsTimerMotif.cpp | 12 +- .../timer/src/unix/motif/nsTimerMotif.h | 20 +- .../widget/timer/src/unix/qt/nsTimerQt.cpp | 12 +- mozilla/widget/timer/src/unix/qt/nsTimerQt.h | 24 +- .../timer/src/unix/xlib/nsTimerXlib.cpp | 10 +- .../widget/timer/src/unix/xlib/nsTimerXlib.h | 19 +- mozilla/widget/timer/src/windows/makefile.win | 6 + mozilla/widget/timer/src/windows/nsTimer.cpp | 477 +++++++----------- .../bookmarks/src/nsBookmarksService.cpp | 36 +- 69 files changed, 848 insertions(+), 522 deletions(-) diff --git a/mozilla/chrome/src/nsChromeProtocolHandler.cpp b/mozilla/chrome/src/nsChromeProtocolHandler.cpp index 3414a13ce6a..c305c5aa7fd 100644 --- a/mozilla/chrome/src/nsChromeProtocolHandler.cpp +++ b/mozilla/chrome/src/nsChromeProtocolHandler.cpp @@ -79,7 +79,7 @@ public: NS_DECL_NSICHANNEL // nsITimerCallback - virtual void Notify(nsITimer* aTimer); + NS_IMETHOD_(void) Notify(nsITimer* aTimer); }; NS_IMPL_ADDREF(nsCachedChromeChannel); @@ -289,7 +289,7 @@ nsCachedChromeChannel::SetNotificationCallbacks(nsIInterfaceRequestor * aNotific } -void +NS_IMETHODIMP_(void) nsCachedChromeChannel::Notify(nsITimer* aTimer) { (void) mListener->OnStopRequest(this, mContext, NS_OK, nsnull); diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index d7d55c7f697..5046db2b84b 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -194,7 +194,7 @@ public: NS_IMETHOD DoFragment(PRBool aFlag); // nsITimerCallback - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); // nsICSSLoaderObserver NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify); @@ -2197,7 +2197,7 @@ HTMLContentSink::DidBuildModel(PRInt32 aQualityLevel) return NS_OK; } -void +NS_IMETHODIMP_(void) HTMLContentSink::Notify(nsITimer *timer) { MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::Notify()\n")); diff --git a/mozilla/content/xul/content/src/nsXULPopupListener.cpp b/mozilla/content/xul/content/src/nsXULPopupListener.cpp index 7ded8db03de..553c1f36e0d 100644 --- a/mozilla/content/xul/content/src/nsXULPopupListener.cpp +++ b/mozilla/content/xul/content/src/nsXULPopupListener.cpp @@ -301,7 +301,7 @@ XULPopupListenerImpl::MouseMove(nsIDOMEvent* aMouseEvent) nsCOMPtr eventTarget; aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); mPossibleTooltipNode = eventTarget.get(); - mTooltipTimer->Init(sTooltipCallback, this, 500); // 500 ms delay + mTooltipTimer->Init(sTooltipCallback, this, 500, NS_PRIORITY_HIGH); // 500 ms delay } else NS_WARNING ( "Could not create a timer for tooltip tracking" ); diff --git a/mozilla/docshell/base/nsWebShell.cpp b/mozilla/docshell/base/nsWebShell.cpp index 323f78308c5..e703504aae6 100644 --- a/mozilla/docshell/base/nsWebShell.cpp +++ b/mozilla/docshell/base/nsWebShell.cpp @@ -3343,7 +3343,7 @@ public: NS_DECL_ISUPPORTS // nsITimerCallback interface - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); nsIWebShell* mShell; nsString mUrlSpec; @@ -3369,7 +3369,7 @@ refreshData::~refreshData() NS_IMPL_ISUPPORTS(refreshData, kITimerCallbackIID); -void refreshData::Notify(nsITimer *aTimer) +NS_IMETHODIMP_(void) refreshData::Notify(nsITimer *aTimer) { NS_PRECONDITION((nsnull != mShell), "Null pointer..."); if (nsnull != mShell) { diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index 7379bbf7987..214f6e1100b 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -2138,7 +2138,7 @@ GlobalWindowImpl::RunTimeout(nsTimeoutImpl *aTimeout) } err = timeout->timer->Init(nsGlobalWindow_RunTimeout, timeout, - delay32); + delay32, NS_PRIORITY_LOWEST); if (NS_OK != err) { NS_RELEASE(temp); NS_RELEASE(tempContext); @@ -2298,7 +2298,7 @@ GlobalWindowImpl::SetTimeoutOrInterval(JSContext *cx, } err = timeout->timer->Init(nsGlobalWindow_RunTimeout, timeout, - (PRInt32)interval); + (PRInt32)interval, NS_PRIORITY_LOWEST); if (NS_OK != err) { DropTimeout(timeout); return err; diff --git a/mozilla/js/src/xpconnect/tests/components/xpctest_echo.cpp b/mozilla/js/src/xpconnect/tests/components/xpctest_echo.cpp index 06f713d1b9d..ca252b20fef 100644 --- a/mozilla/js/src/xpconnect/tests/components/xpctest_echo.cpp +++ b/mozilla/js/src/xpconnect/tests/components/xpctest_echo.cpp @@ -43,7 +43,7 @@ public: NS_DECL_NSIECHO // not very xpcom compilant method from nsITimerCallback - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); xpctestEcho(); virtual ~xpctestEcho(); @@ -424,7 +424,7 @@ xpctestEcho::CallReceiverSometimeLater(void) #endif } -void +NS_IMETHODIMP_(void) xpctestEcho::Notify(nsITimer *timer) { if(mReceiver) diff --git a/mozilla/layout/base/nsCaret.cpp b/mozilla/layout/base/nsCaret.cpp index a245c952fc9..00c8606bcce 100644 --- a/mozilla/layout/base/nsCaret.cpp +++ b/mozilla/layout/base/nsCaret.cpp @@ -347,7 +347,7 @@ nsresult nsCaret::PrimeTimer() if (NS_FAILED(err)) return err; - mBlinkTimer->Init(CaretBlinkCallback, this, mBlinkRate); + mBlinkTimer->Init(CaretBlinkCallback, this, mBlinkRate, NS_PRIORITY_HIGH, NS_TYPE_REPEATING_PRECISE); } return NS_OK; @@ -688,7 +688,10 @@ void nsCaret::CaretBlinkCallback(nsITimer *aTimer, void *aClosure) if (!theCaret) return; theCaret->DrawCaret(); + +#ifndef REPEATING_TIMERS theCaret->PrimeTimer(); +#endif } diff --git a/mozilla/layout/base/src/nsCaret.cpp b/mozilla/layout/base/src/nsCaret.cpp index a245c952fc9..00c8606bcce 100644 --- a/mozilla/layout/base/src/nsCaret.cpp +++ b/mozilla/layout/base/src/nsCaret.cpp @@ -347,7 +347,7 @@ nsresult nsCaret::PrimeTimer() if (NS_FAILED(err)) return err; - mBlinkTimer->Init(CaretBlinkCallback, this, mBlinkRate); + mBlinkTimer->Init(CaretBlinkCallback, this, mBlinkRate, NS_PRIORITY_HIGH, NS_TYPE_REPEATING_PRECISE); } return NS_OK; @@ -688,7 +688,10 @@ void nsCaret::CaretBlinkCallback(nsITimer *aTimer, void *aClosure) if (!theCaret) return; theCaret->DrawCaret(); + +#ifndef REPEATING_TIMERS theCaret->PrimeTimer(); +#endif } diff --git a/mozilla/layout/base/src/nsRangeList.cpp b/mozilla/layout/base/src/nsRangeList.cpp index 4c521ca0493..baf965da4fd 100644 --- a/mozilla/layout/base/src/nsRangeList.cpp +++ b/mozilla/layout/base/src/nsRangeList.cpp @@ -389,7 +389,7 @@ public: return NS_OK; } - virtual void Notify(nsITimer *timer) + NS_IMETHOD_(void) Notify(nsITimer *timer) { if (mSelection && mPresContext && mFrame) { diff --git a/mozilla/layout/generic/nsObjectFrame.cpp b/mozilla/layout/generic/nsObjectFrame.cpp index 99d13c78383..e17a662c745 100644 --- a/mozilla/layout/generic/nsObjectFrame.cpp +++ b/mozilla/layout/generic/nsObjectFrame.cpp @@ -144,7 +144,7 @@ public: void Paint(const nsRect& aDirtyRect, PRUint32 ndc = nsnull); // nsITimerCallback interface - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); void CancelTimer(); @@ -2332,7 +2332,7 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, PRUint32 ndc) // Here's how we give idle time to plugins. -void nsPluginInstanceOwner::Notify(nsITimer* /* timer */) +NS_IMETHODIMP_(void) nsPluginInstanceOwner::Notify(nsITimer* /* timer */) { #ifdef XP_MAC if (mInstance != NULL) { @@ -2348,11 +2348,13 @@ void nsPluginInstanceOwner::Notify(nsITimer* /* timer */) } #endif +#ifndef REPEATING_TIMERS // reprime the timer? currently have to create a new timer for each call, which is // kind of wasteful. need to get periodic timers working on all platforms. NS_IF_RELEASE(mPluginTimer); if (NS_NewTimer(&mPluginTimer) == NS_OK) mPluginTimer->Init(this, 1000 / 60); +#endif } void nsPluginInstanceOwner::CancelTimer() @@ -2443,7 +2445,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void) // start a periodic timer to provide null events to the plugin instance. rv = NS_NewTimer(&mPluginTimer); if (rv == NS_OK) - rv = mPluginTimer->Init(this, 1000 / 60); + rv = mPluginTimer->Init(this, 1000 / 60, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); #endif } } diff --git a/mozilla/layout/generic/nsTextFrame.cpp b/mozilla/layout/generic/nsTextFrame.cpp index dbbe0d3399e..089acc84710 100644 --- a/mozilla/layout/generic/nsTextFrame.cpp +++ b/mozilla/layout/generic/nsTextFrame.cpp @@ -158,7 +158,7 @@ public: void Stop(); - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); struct FrameData { nsIPresContext* mPresContext; // pres context associated with the frame @@ -196,7 +196,7 @@ void nsBlinkTimer::Start() { nsresult rv = NS_NewTimer(&mTimer); if (NS_OK == rv) { - mTimer->Init(this, 750); + mTimer->Init(this, 750, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_PRECISE); } } @@ -242,17 +242,19 @@ PRInt32 nsBlinkTimer::FrameCount() { return mFrames.Count(); } -void nsBlinkTimer::Notify(nsITimer *timer) +NS_IMETHODIMP_(void) nsBlinkTimer::Notify(nsITimer *timer) { // Toggle blink state bit so that text code knows whether or not to // render. All text code shares the same flag so that they all blink // in unison. gBlinkTextOff = PRBool(!gBlinkTextOff); +#ifndef REPEATING_TIMERS // XXX hack to get auto-repeating timers; restart before doing // expensive work so that time between ticks is more even Stop(); Start(); +#endif #ifdef NOISY_BLINK PRTime now = PR_Now(); diff --git a/mozilla/layout/html/base/src/nsObjectFrame.cpp b/mozilla/layout/html/base/src/nsObjectFrame.cpp index 99d13c78383..e17a662c745 100644 --- a/mozilla/layout/html/base/src/nsObjectFrame.cpp +++ b/mozilla/layout/html/base/src/nsObjectFrame.cpp @@ -144,7 +144,7 @@ public: void Paint(const nsRect& aDirtyRect, PRUint32 ndc = nsnull); // nsITimerCallback interface - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); void CancelTimer(); @@ -2332,7 +2332,7 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, PRUint32 ndc) // Here's how we give idle time to plugins. -void nsPluginInstanceOwner::Notify(nsITimer* /* timer */) +NS_IMETHODIMP_(void) nsPluginInstanceOwner::Notify(nsITimer* /* timer */) { #ifdef XP_MAC if (mInstance != NULL) { @@ -2348,11 +2348,13 @@ void nsPluginInstanceOwner::Notify(nsITimer* /* timer */) } #endif +#ifndef REPEATING_TIMERS // reprime the timer? currently have to create a new timer for each call, which is // kind of wasteful. need to get periodic timers working on all platforms. NS_IF_RELEASE(mPluginTimer); if (NS_NewTimer(&mPluginTimer) == NS_OK) mPluginTimer->Init(this, 1000 / 60); +#endif } void nsPluginInstanceOwner::CancelTimer() @@ -2443,7 +2445,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void) // start a periodic timer to provide null events to the plugin instance. rv = NS_NewTimer(&mPluginTimer); if (rv == NS_OK) - rv = mPluginTimer->Init(this, 1000 / 60); + rv = mPluginTimer->Init(this, 1000 / 60, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); #endif } } diff --git a/mozilla/layout/html/base/src/nsTextFrame.cpp b/mozilla/layout/html/base/src/nsTextFrame.cpp index dbbe0d3399e..089acc84710 100644 --- a/mozilla/layout/html/base/src/nsTextFrame.cpp +++ b/mozilla/layout/html/base/src/nsTextFrame.cpp @@ -158,7 +158,7 @@ public: void Stop(); - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); struct FrameData { nsIPresContext* mPresContext; // pres context associated with the frame @@ -196,7 +196,7 @@ void nsBlinkTimer::Start() { nsresult rv = NS_NewTimer(&mTimer); if (NS_OK == rv) { - mTimer->Init(this, 750); + mTimer->Init(this, 750, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_PRECISE); } } @@ -242,17 +242,19 @@ PRInt32 nsBlinkTimer::FrameCount() { return mFrames.Count(); } -void nsBlinkTimer::Notify(nsITimer *timer) +NS_IMETHODIMP_(void) nsBlinkTimer::Notify(nsITimer *timer) { // Toggle blink state bit so that text code knows whether or not to // render. All text code shares the same flag so that they all blink // in unison. gBlinkTextOff = PRBool(!gBlinkTextOff); +#ifndef REPEATING_TIMERS // XXX hack to get auto-repeating timers; restart before doing // expensive work so that time between ticks is more even Stop(); Start(); +#endif #ifdef NOISY_BLINK PRTime now = PR_Now(); diff --git a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp index d7d55c7f697..5046db2b84b 100644 --- a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp @@ -194,7 +194,7 @@ public: NS_IMETHOD DoFragment(PRBool aFlag); // nsITimerCallback - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); // nsICSSLoaderObserver NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify); @@ -2197,7 +2197,7 @@ HTMLContentSink::DidBuildModel(PRInt32 aQualityLevel) return NS_OK; } -void +NS_IMETHODIMP_(void) HTMLContentSink::Notify(nsITimer *timer) { MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::Notify()\n")); diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.cpp b/mozilla/layout/xul/base/src/nsMenuFrame.cpp index d54a8b35a68..135aadf23b1 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuFrame.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Michael Lowe */ #include "nsXULAtoms.h" @@ -46,6 +47,9 @@ #include "nsIDOMElement.h" #include "nsISupportsArray.h" #include "nsIDOMText.h" +#include "nsILookAndFeel.h" +#include "nsIComponentManager.h" +#include "nsWidgetsCID.h" #define NS_MENU_POPUP_LIST_INDEX (NS_AREA_FRAME_ABSOLUTE_LIST_INDEX + 1) @@ -53,6 +57,10 @@ static PRInt32 gEatMouseMove = PR_FALSE; nsMenuDismissalListener* nsMenuFrame::mDismissalListener = nsnull; +static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); +static NS_DEFINE_IID(kILookAndFeelIID, NS_ILOOKANDFEEL_IID); + + // // NS_NewMenuFrame // @@ -326,9 +334,19 @@ nsMenuFrame::HandleEvent(nsIPresContext* aPresContext, // If we're a menu (and not a menu item), // kick off the timer. if (!isMenuBar && IsMenu() && !mMenuOpen && !mOpenTimer) { - // We're a menu, we're built, we're closed, and no timer has been kicked off. - NS_NewTimer(getter_AddRefs(mOpenTimer)); - mOpenTimer->Init(this, 250); // 250 ms delay + + PRInt32 menuDelay = 250; // ms + + nsILookAndFeel * lookAndFeel; + if (NS_OK == nsComponentManager::CreateInstance(kLookAndFeelCID, nsnull, + kILookAndFeelIID, (void**)&lookAndFeel)) { + lookAndFeel->GetMetric(nsILookAndFeel::eMetric_SubmenuDelay, menuDelay); + NS_RELEASE(lookAndFeel); + } + + // We're a menu, we're built, we're closed, and no timer has been kicked off. + NS_NewTimer(getter_AddRefs(mOpenTimer)); + mOpenTimer->Init(this, menuDelay, NS_PRIORITY_HIGHEST); } } return NS_OK; @@ -823,7 +841,7 @@ nsMenuFrame::IsMenu() return PR_FALSE; } -void +NS_IMETHODIMP_(void) nsMenuFrame::Notify(nsITimer* aTimer) { // Our timer has fired. diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.h b/mozilla/layout/xul/base/src/nsMenuFrame.h index 57fe10c344a..5e9539ee66c 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuFrame.h @@ -62,7 +62,7 @@ public: NS_IMETHOD CreateAnonymousContent(nsISupportsArray& aAnonymousItems); // The nsITimerCallback interface - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, diff --git a/mozilla/layout/xul/base/src/nsProgressMeterFrame.cpp b/mozilla/layout/xul/base/src/nsProgressMeterFrame.cpp index 985cf433500..313956a25c8 100644 --- a/mozilla/layout/xul/base/src/nsProgressMeterFrame.cpp +++ b/mozilla/layout/xul/base/src/nsProgressMeterFrame.cpp @@ -66,7 +66,7 @@ public: void Stop(); - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); PRInt32 GetFrameData(nsProgressMeterFrame* aFrame); @@ -101,7 +101,7 @@ void StripeTimer::Start() { nsresult rv = NS_NewTimer(&mTimer); if (NS_OK == rv) { - mTimer->Init(this, ANIMATION_SPEED); + mTimer->Init(this, ANIMATION_SPEED, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); } } @@ -163,12 +163,14 @@ PRInt32 StripeTimer::FrameCount() { return mFrames.Count(); } -void StripeTimer::Notify(nsITimer *timer) +NS_IMETHODIMP_(void) StripeTimer::Notify(nsITimer *timer) { // XXX hack to get auto-repeating timers; restart before doing // expensive work so that time between ticks is more even +#ifndef REPEATING_TIMERS Stop(); Start(); +#endif PRInt32 i, n = mFrames.Count(); for (i = 0; i < n; i++) { diff --git a/mozilla/layout/xul/base/src/nsRepeatService.cpp b/mozilla/layout/xul/base/src/nsRepeatService.cpp index d963c627f59..f8a4a657abe 100644 --- a/mozilla/layout/xul/base/src/nsRepeatService.cpp +++ b/mozilla/layout/xul/base/src/nsRepeatService.cpp @@ -79,7 +79,7 @@ void nsRepeatService::Stop() } } -void nsRepeatService::Notify(nsITimer *timer) +NS_IMETHODIMP_(void) nsRepeatService::Notify(nsITimer *timer) { // if the repeat delay is the initial one reset it. if (mRepeatTimer) { diff --git a/mozilla/layout/xul/base/src/nsRepeatService.h b/mozilla/layout/xul/base/src/nsRepeatService.h index 7fd8a1f1d52..8740485e0b4 100644 --- a/mozilla/layout/xul/base/src/nsRepeatService.h +++ b/mozilla/layout/xul/base/src/nsRepeatService.h @@ -36,7 +36,7 @@ class nsRepeatService : public nsITimerCallback { public: - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); void Start(nsITimerCallback* aCallback); void Stop(); diff --git a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp index 49ae98c5cee..5d6bfbaeed6 100644 --- a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp +++ b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp @@ -113,7 +113,7 @@ nsScrollbarButtonFrame::HandleRelease(nsIPresContext* aPresContext, } -void nsScrollbarButtonFrame::Notify(nsITimer *timer) +NS_IMETHODIMP_(void) nsScrollbarButtonFrame::Notify(nsITimer *timer) { MouseClicked(); } diff --git a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.h b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.h index 2bcc8ef51bc..7584c295091 100644 --- a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.h +++ b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.h @@ -69,7 +69,7 @@ public: nsGUIEvent * aEvent, nsEventStatus* aEventStatus); - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } diff --git a/mozilla/layout/xul/base/src/nsSliderFrame.cpp b/mozilla/layout/xul/base/src/nsSliderFrame.cpp index aa25bc2551f..ec0939731f3 100644 --- a/mozilla/layout/xul/base/src/nsSliderFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSliderFrame.cpp @@ -977,7 +977,7 @@ nsSliderFrame::SetScrollbarListener(nsIScrollbarListener* aListener) mScrollbarListener = aListener; } -void nsSliderFrame::Notify(nsITimer *timer) +NS_IMETHODIMP_(void) nsSliderFrame::Notify(nsITimer *timer) { nsIFrame* thumbFrame = mFrames.FirstChild(); PageUpDown(thumbFrame, gChange); diff --git a/mozilla/layout/xul/base/src/nsSliderFrame.h b/mozilla/layout/xul/base/src/nsSliderFrame.h index 1d682caa7cb..8263025f823 100644 --- a/mozilla/layout/xul/base/src/nsSliderFrame.h +++ b/mozilla/layout/xul/base/src/nsSliderFrame.h @@ -195,7 +195,7 @@ public: nsGUIEvent * aEvent, nsEventStatus* aEventStatus); - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); protected: diff --git a/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp b/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp index 3414a13ce6a..c305c5aa7fd 100644 --- a/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp +++ b/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp @@ -79,7 +79,7 @@ public: NS_DECL_NSICHANNEL // nsITimerCallback - virtual void Notify(nsITimer* aTimer); + NS_IMETHOD_(void) Notify(nsITimer* aTimer); }; NS_IMPL_ADDREF(nsCachedChromeChannel); @@ -289,7 +289,7 @@ nsCachedChromeChannel::SetNotificationCallbacks(nsIInterfaceRequestor * aNotific } -void +NS_IMETHODIMP_(void) nsCachedChromeChannel::Notify(nsITimer* aTimer) { (void) mListener->OnStopRequest(this, mContext, NS_OK, nsnull); diff --git a/mozilla/rdf/content/src/nsXULPopupListener.cpp b/mozilla/rdf/content/src/nsXULPopupListener.cpp index 7ded8db03de..553c1f36e0d 100644 --- a/mozilla/rdf/content/src/nsXULPopupListener.cpp +++ b/mozilla/rdf/content/src/nsXULPopupListener.cpp @@ -301,7 +301,7 @@ XULPopupListenerImpl::MouseMove(nsIDOMEvent* aMouseEvent) nsCOMPtr eventTarget; aMouseEvent->GetTarget(getter_AddRefs(eventTarget)); mPossibleTooltipNode = eventTarget.get(); - mTooltipTimer->Init(sTooltipCallback, this, 500); // 500 ms delay + mTooltipTimer->Init(sTooltipCallback, this, 500, NS_PRIORITY_HIGH); // 500 ms delay } else NS_WARNING ( "Could not create a timer for tooltip tracking" ); diff --git a/mozilla/view/src/nsScrollPortView.h b/mozilla/view/src/nsScrollPortView.h index 0eef0c81bee..fc5d0d87dc4 100644 --- a/mozilla/view/src/nsScrollPortView.h +++ b/mozilla/view/src/nsScrollPortView.h @@ -112,7 +112,7 @@ protected: virtual ~nsScrollPortView(); // nsITimerCallback Interface - //virtual void Notify(nsITimer *timer); + //NS_IMETHOD_(void) Notify(nsITimer *timer); //private void AdjustChildWidgets(nsScrollPortView *aScrolling, nsIView *aView, nscoord aDx, nscoord aDy, float aScale); diff --git a/mozilla/view/src/nsScrollingView.cpp b/mozilla/view/src/nsScrollingView.cpp index 509762755c8..5f56c962e3b 100644 --- a/mozilla/view/src/nsScrollingView.cpp +++ b/mozilla/view/src/nsScrollingView.cpp @@ -743,7 +743,7 @@ void nsScrollingView::HandleScrollEvent(nsGUIEvent *aEvent, PRUint32 aEventFlags NotifyScrollPositionDidChange(offsetX, offsetY); } -void nsScrollingView::Notify(nsITimer * aTimer) +NS_IMETHODIMP_(void) nsScrollingView::Notify(nsITimer * aTimer) { nscoord xoff, yoff; nsIView *view; @@ -782,7 +782,7 @@ void nsScrollingView::Notify(nsITimer * aTimer) obs->HandleEvent((nsIView *)this, &event, &retval); NS_RELEASE(obs); } - + NS_RELEASE(mScrollingTimer); if (NS_OK == NS_NewTimer(&mScrollingTimer)) diff --git a/mozilla/view/src/nsScrollingView.h b/mozilla/view/src/nsScrollingView.h index c732d5db918..eae4342d927 100644 --- a/mozilla/view/src/nsScrollingView.h +++ b/mozilla/view/src/nsScrollingView.h @@ -116,7 +116,7 @@ protected: virtual ~nsScrollingView(); // nsITimerCallback Interface - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); //private void AdjustChildWidgets(nsScrollingView *aScrolling, nsIView *aView, nscoord aDx, nscoord aDy, float aScale); diff --git a/mozilla/webshell/src/nsWebShell.cpp b/mozilla/webshell/src/nsWebShell.cpp index 323f78308c5..e703504aae6 100644 --- a/mozilla/webshell/src/nsWebShell.cpp +++ b/mozilla/webshell/src/nsWebShell.cpp @@ -3343,7 +3343,7 @@ public: NS_DECL_ISUPPORTS // nsITimerCallback interface - virtual void Notify(nsITimer *timer); + NS_IMETHOD_(void) Notify(nsITimer *timer); nsIWebShell* mShell; nsString mUrlSpec; @@ -3369,7 +3369,7 @@ refreshData::~refreshData() NS_IMPL_ISUPPORTS(refreshData, kITimerCallbackIID); -void refreshData::Notify(nsITimer *aTimer) +NS_IMETHODIMP_(void) refreshData::Notify(nsITimer *aTimer) { NS_PRECONDITION((nsnull != mShell), "Null pointer..."); if (nsnull != mShell) { diff --git a/mozilla/webshell/tests/viewer/nsSetupRegistry.cpp b/mozilla/webshell/tests/viewer/nsSetupRegistry.cpp index 8cabdc521d4..4f41222d3e6 100644 --- a/mozilla/webshell/tests/viewer/nsSetupRegistry.cpp +++ b/mozilla/webshell/tests/viewer/nsSetupRegistry.cpp @@ -136,6 +136,8 @@ static NS_DEFINE_IID(kCMenuBarCID, NS_MENUBAR_CID); static NS_DEFINE_IID(kCMenuCID, NS_MENU_CID); static NS_DEFINE_IID(kCMenuItemCID, NS_MENUITEM_CID); static NS_DEFINE_IID(kCContextMenuCID, NS_CONTEXTMENU_CID); +static NS_DEFINE_IID(kCTimerCID, NS_TIMER_CID); +static NS_DEFINE_IID(kCTimerManagerCID, NS_TIMERMANAGER_CID); //static NS_DEFINE_IID(kCXULCommandCID, NS_XULCOMMAND_CID); static NS_DEFINE_IID(kSoundCID, NS_SOUND_CID); static NS_DEFINE_CID(kFileSpecWithUICID, NS_FILESPECWITHUI_CID); @@ -326,6 +328,10 @@ NS_SetupRegistry() nsComponentManager::RegisterComponentLib(kCXIFFormatConverterCID, NULL, NULL, WIDGET_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponentLib(kCDragServiceCID, "Drag Service", "component://netscape/widget/dragservice", WIDGET_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponentLib(kCFontRetrieverServiceCID, NULL, NULL, WIDGET_DLL, PR_FALSE, PR_FALSE); +#ifdef XP_PC + nsComponentManager::RegisterComponentLib(kCTimerCID, NULL, NULL, WIDGET_DLL, PR_FALSE, PR_FALSE); + nsComponentManager::RegisterComponentLib(kCTimerManagerCID, NULL, NULL, WIDGET_DLL, PR_FALSE, PR_FALSE); +#endif nsComponentManager::RegisterComponentLib(kCMenuBarCID, NULL, NULL, WIDGET_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponentLib(kCMenuCID, NULL, NULL, WIDGET_DLL, PR_FALSE, PR_FALSE); nsComponentManager::RegisterComponentLib(kCMenuItemCID, NULL, NULL, WIDGET_DLL, PR_FALSE, PR_FALSE); diff --git a/mozilla/webshell/tests/viewer/nsThrobber.cpp b/mozilla/webshell/tests/viewer/nsThrobber.cpp index eb171bfa7ff..87c45f2dd4d 100644 --- a/mozilla/webshell/tests/viewer/nsThrobber.cpp +++ b/mozilla/webshell/tests/viewer/nsThrobber.cpp @@ -312,12 +312,14 @@ nsThrobber::Tick() mCompletedImages = 0; } +#ifndef REPEATING_TIMERS NS_RELEASE(mTimer); nsresult rv = NS_NewTimer(&mTimer); if (NS_OK == rv) { mTimer->Init(ThrobTimerCallback, this, 33); } +#endif } nsresult @@ -343,7 +345,7 @@ nsThrobber::LoadThrobberImages(const nsString& aFileNameMask, PRInt32 aNumImages if (NS_OK != rv) { return rv; } - mTimer->Init(ThrobTimerCallback, this, 33); + mTimer->Init(ThrobTimerCallback, this, 33, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); char * mask = aFileNameMask.ToNewCString(); for (PRInt32 cnt = 0; cnt < mNumImages; cnt++) diff --git a/mozilla/webshell/tests/viewer/nsWinMain.cpp b/mozilla/webshell/tests/viewer/nsWinMain.cpp index 454928f24c1..5b4ac2e3ce9 100644 --- a/mozilla/webshell/tests/viewer/nsWinMain.cpp +++ b/mozilla/webshell/tests/viewer/nsWinMain.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Michael Lowe */ #include #include "nsViewerApp.h" @@ -27,10 +28,13 @@ #include "plevent.h" #include "nsIServiceManager.h" #include "nsIThread.h" +#include "nsWidgetsCID.h" +#include "nsTimerManager.h" JSConsole *gConsole; HINSTANCE gInstance, gPrevInstance; static nsITimer* gNetTimer; +static NS_DEFINE_CID(kTimerManagerCID, NS_TIMERMANAGER_CID); nsNativeViewerApp::nsNativeViewerApp() { @@ -40,6 +44,7 @@ nsNativeViewerApp::~nsNativeViewerApp() { } + int nsNativeViewerApp::Run() { @@ -52,26 +57,41 @@ nsNativeViewerApp::Run() MSG msg; int keepGoing = 1; + nsresult rv; + NS_WITH_SERVICE(nsITimerQueue, queue, kTimerManagerCID, &rv); + if (NS_FAILED(rv)) return 0; + // Pump all messages do { // Give priority to system messages (in particular keyboard, mouse, // timer, and paint messages). // Note: on Win98 and NT 5.0 we can also use PM_QS_INPUT and PM_QS_PAINT flags. - if (::PeekMessage(&msg, NULL, 0, WM_USER-1, PM_REMOVE)) { - keepGoing = (msg.message != WM_QUIT); - - } else { - // Block and wait for any posted application message - keepGoing = ::GetMessage(&msg, NULL, 0, 0); - } + if (::PeekMessage(&msg, NULL, 0, WM_USER-1, PM_REMOVE) || + ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - // If we successfully retrieved a message then dispatch it - if (keepGoing >= 0) { - if (!JSConsole::sAccelTable || !gConsole || !gConsole->GetMainWindow() || + keepGoing = (msg.message != WM_QUIT); + + // If we successfully retrieved a message then dispatch it + if (keepGoing >= 0) { + if (!JSConsole::sAccelTable || !gConsole || !gConsole->GetMainWindow() || !TranslateAccelerator(gConsole->GetMainWindow(), JSConsole::sAccelTable, &msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + TranslateMessage(&msg); + DispatchMessage(&msg); + } } + + // process timer queue. + } else if (queue->HasReadyTimers(NS_PRIORITY_LOWEST)) { + + do { + //printf("fire\n"); + queue->FireNextReadyTimer(NS_PRIORITY_LOWEST); + } while (queue->HasReadyTimers(NS_PRIORITY_LOWEST) && + !::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)); + + } else { + // Block and wait for any posted application message + ::WaitMessage(); } } while (keepGoing != 0); diff --git a/mozilla/widget/public/nsILookAndFeel.h b/mozilla/widget/public/nsILookAndFeel.h index 5b337969dfe..0c67550809c 100644 --- a/mozilla/widget/public/nsILookAndFeel.h +++ b/mozilla/widget/public/nsILookAndFeel.h @@ -109,7 +109,8 @@ public: eMetric_ListVerticalInsidePadding, // needed only because of GTK eMetric_CaretBlinkTime, // default, may be overriden by OS - eMetric_CaretWidthTwips + eMetric_CaretWidthTwips, + eMetric_SubmenuDelay } nsMetricID; typedef enum { diff --git a/mozilla/widget/public/nsWidgetsCID.h b/mozilla/widget/public/nsWidgetsCID.h index 4116d2c6f87..75695161742 100644 --- a/mozilla/widget/public/nsWidgetsCID.h +++ b/mozilla/widget/public/nsWidgetsCID.h @@ -162,6 +162,16 @@ #define NS_FONTRETRIEVERSERVICE_CID \ { 0x285ef9b2, 0x94a, 0x11d3, { 0x9a, 0x87, 0x0, 0x50, 0x4, 0x6c, 0xda, 0x96 } } +// {6B6C423A-1DD2-11B2-8888-E540BB169DDD} +#define NS_TIMER_CID \ +{ 0x6b6c423a, 0x1dd2, 0x11b2, \ + { 0x88, 0x88, 0xe5, 0x40, 0xbb, 0x16, 0x9d, 0xdd } } + +// {7783D5A6-1DD2-11B2-BF5E-CA89083D0AA4} +#define NS_TIMERMANAGER_CID \ +{ 0x7783d5a6, 0x1dd2, 0x11b2, \ + { 0xbf, 0x5e, 0xca, 0x89, 0x8, 0x3d, 0xa, 0xa4 } } + //----------------------------------------------------------- //Drag & Drop & Clipboard //----------------------------------------------------------- diff --git a/mozilla/widget/src/beos/nsLookAndFeel.cpp b/mozilla/widget/src/beos/nsLookAndFeel.cpp index 2c751fc7bc2..670a960532f 100644 --- a/mozilla/widget/src/beos/nsLookAndFeel.cpp +++ b/mozilla/widget/src/beos/nsLookAndFeel.cpp @@ -149,6 +149,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_CaretWidthTwips: aMetric = 20; break; + case eMetric_SubmenuDelay: + aMetric = 200; + break; default: aMetric = -1; res = NS_ERROR_FAILURE; diff --git a/mozilla/widget/src/build/makefile.win b/mozilla/widget/src/build/makefile.win index 491d05c7049..824a967f559 100644 --- a/mozilla/widget/src/build/makefile.win +++ b/mozilla/widget/src/build/makefile.win @@ -62,6 +62,7 @@ LLIBS= \ $(DIST)\lib\gkgfxwin.lib \ $(DIST)\lib\raptorbasewidget_s.lib \ $(DIST)\lib\raptorwidget_s.lib \ + $(DIST)\lib\timer_s.lib \ $(LIBNSPR) include <$(DEPTH)\config\rules.mak> diff --git a/mozilla/widget/src/build/nsWinWidgetFactory.cpp b/mozilla/widget/src/build/nsWinWidgetFactory.cpp index e9a41d12aa9..98e4203b818 100644 --- a/mozilla/widget/src/build/nsWinWidgetFactory.cpp +++ b/mozilla/widget/src/build/nsWinWidgetFactory.cpp @@ -78,6 +78,9 @@ #include "nsSound.h" +#include "nsWindowsTimer.h" + +#include "nsTimerManager.h" // Drag & Drop, Clipboard @@ -136,6 +139,9 @@ static NS_DEFINE_IID(kCPopUpMenu, NS_POPUPMENU_CID); static NS_DEFINE_IID(kCFontRetrieverService, NS_FONTRETRIEVERSERVICE_CID); +static NS_DEFINE_IID(kCTimer, NS_TIMER_CID); + +static NS_DEFINE_IID(kCTimerManager, NS_TIMERMANAGER_CID); // Drag & Drop, Clipboard @@ -479,7 +485,17 @@ nsresult nsWidgetFactory::CreateInstance( nsISupports* aOuter, } + else if (mClassID.Equals(kCTimer)) { + inst = (nsISupports*)(nsITimer*) new nsTimer(); + + } + + else if (mClassID.Equals(kCTimerManager)) { + + inst = (nsISupports*)(nsITimerQueue*) new nsTimerManager(); + + } /* */ diff --git a/mozilla/widget/src/gtk/nsLookAndFeel.cpp b/mozilla/widget/src/gtk/nsLookAndFeel.cpp index 227b4b6719b..9feee53f1e0 100644 --- a/mozilla/widget/src/gtk/nsLookAndFeel.cpp +++ b/mozilla/widget/src/gtk/nsLookAndFeel.cpp @@ -260,6 +260,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_CaretWidthTwips: aMetric = 20; break; + case eMetric_SubmenuDelay: + aMetric = 200; + break; default: aMetric = 0; res = NS_ERROR_FAILURE; diff --git a/mozilla/widget/src/gtk/nsWindow.cpp b/mozilla/widget/src/gtk/nsWindow.cpp index 42b81c0878f..e75720b4422 100644 --- a/mozilla/widget/src/gtk/nsWindow.cpp +++ b/mozilla/widget/src/gtk/nsWindow.cpp @@ -1979,7 +1979,7 @@ nsresult nsWindow::SetIcon(GdkPixmap *pixmap, -void nsWindow::Notify(nsITimer* aTimer) +NS_IMETHODIMP_(void) nsWindow::Notify(nsITimer* aTimer) { // printf("%p nsWindow::Notify()\n", this); mUpdateArea->Intersect(0, 0, mBounds.width, mBounds.height); diff --git a/mozilla/widget/src/gtk/nsWindow.h b/mozilla/widget/src/gtk/nsWindow.h index 29ebafea793..ed1ab3d7678 100644 --- a/mozilla/widget/src/gtk/nsWindow.h +++ b/mozilla/widget/src/gtk/nsWindow.h @@ -53,7 +53,7 @@ public: NS_DECL_ISUPPORTS_INHERITED // nsITimerCallback - virtual void Notify(nsITimer* aTimer); + NS_IMETHOD_(void) Notify(nsITimer* aTimer); NS_IMETHOD WidgetToScreen(const nsRect &aOldRect, nsRect &aNewRect); diff --git a/mozilla/widget/src/mac/nsLookAndFeel.cpp b/mozilla/widget/src/mac/nsLookAndFeel.cpp index 48c9cd131b6..c01ca44d451 100644 --- a/mozilla/widget/src/mac/nsLookAndFeel.cpp +++ b/mozilla/widget/src/mac/nsLookAndFeel.cpp @@ -249,6 +249,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_CaretWidthTwips: aMetric = 20; break; + case eMetric_SubmenuDelay: + aMetric = 200; + break; default: aMetric = 0; res = NS_ERROR_FAILURE; diff --git a/mozilla/widget/src/motif/nsLookAndFeel.cpp b/mozilla/widget/src/motif/nsLookAndFeel.cpp index d38a18a8625..7429fb0054e 100644 --- a/mozilla/widget/src/motif/nsLookAndFeel.cpp +++ b/mozilla/widget/src/motif/nsLookAndFeel.cpp @@ -120,6 +120,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_CaretWidthTwips: aMetric = 20; break; + case eMetric_SubmenuDelay: + aMetric = 200; + break; default: aMetric = 0; res = NS_ERROR_FAILURE; diff --git a/mozilla/widget/src/os2/nsLookAndFeel.cpp b/mozilla/widget/src/os2/nsLookAndFeel.cpp index a82818f2c8e..6b5fec08be9 100644 --- a/mozilla/widget/src/os2/nsLookAndFeel.cpp +++ b/mozilla/widget/src/os2/nsLookAndFeel.cpp @@ -144,6 +144,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) // For now, lets assume p2t = 20. aMetric = 20 * ulPels; break; + case eMetric_SubmenuDelay: + aMetric = 200; + break; default: NS_ASSERTION( 0, "Bad metric"); diff --git a/mozilla/widget/src/photon/nsLookAndFeel.cpp b/mozilla/widget/src/photon/nsLookAndFeel.cpp index 62e1135e0e5..2ad7ade489f 100644 --- a/mozilla/widget/src/photon/nsLookAndFeel.cpp +++ b/mozilla/widget/src/photon/nsLookAndFeel.cpp @@ -168,6 +168,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_CaretWidthTwips: aMetric = 20; break; + case eMetric_SubmenuDelay: + aMetric = 200; + break; default: aMetric = -1; res = NS_ERROR_FAILURE; diff --git a/mozilla/widget/src/qt/nsLookAndFeel.cpp b/mozilla/widget/src/qt/nsLookAndFeel.cpp index da8364cfb98..ce582cce5cf 100644 --- a/mozilla/widget/src/qt/nsLookAndFeel.cpp +++ b/mozilla/widget/src/qt/nsLookAndFeel.cpp @@ -172,6 +172,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_CaretWidthTwips: aMetric = 20; break; + case eMetric_SubmenuDelay: + aMetric = 200; + break; default: aMetric = -1; res = NS_ERROR_FAILURE; diff --git a/mozilla/widget/src/windows/nsAppShell.cpp b/mozilla/widget/src/windows/nsAppShell.cpp index c66cc7fa0a2..39d0045c837 100644 --- a/mozilla/widget/src/windows/nsAppShell.cpp +++ b/mozilla/widget/src/windows/nsAppShell.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Michael Lowe */ #include "nsAppShell.h" @@ -26,11 +27,15 @@ #include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include +#include "nsWidgetsCID.h" +#include "nsITimer.h" +#include "nsITimerQueue.h" #ifdef MOZ_AIMM #include "aimm.h" #endif static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +static NS_DEFINE_CID(kTimerManagerCID, NS_TIMERMANAGER_CID); NS_IMPL_ISUPPORTS(nsAppShell, NS_IAPPSHELL_IID) @@ -77,13 +82,18 @@ NS_METHOD nsAppShell::Run(void) MSG msg; int keepGoing = 1; + nsresult rv; + NS_WITH_SERVICE(nsITimerQueue, queue, kTimerManagerCID, &rv); + if (NS_FAILED(rv)) return rv; + // Process messages do { // Give priority to system messages (in particular keyboard, mouse, // timer, and paint messages). - // Note: on Win98 and NT 5.0 we can also use PM_QS_INPUT and PM_QS_PAINT flags. - if (::PeekMessage(&msg, NULL, 0, WM_USER-1, PM_REMOVE) || - ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (::PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) || + ::PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || + ::PeekMessage(&msg, NULL, 0, WM_USER-1, PM_REMOVE) || + ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { keepGoing = (msg.message != WM_QUIT); @@ -96,6 +106,15 @@ NS_METHOD nsAppShell::Run(void) if (mDispatchListener) mDispatchListener->AfterDispatch(); } + + // process timer queue. + } else if (queue->HasReadyTimers(NS_PRIORITY_LOWEST)) { + + do { + queue->FireNextReadyTimer(NS_PRIORITY_LOWEST); + } while (queue->HasReadyTimers(NS_PRIORITY_LOWEST) && + !::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)); + } else { // Block and wait for any posted application message ::WaitMessage(); @@ -120,23 +139,49 @@ nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *&aEvent) { static MSG msg; - BOOL isOK = GetMessage(&msg, NULL, 0, 0); + BOOL gotMessage = false; + + nsresult rv; + NS_WITH_SERVICE(nsITimerQueue, queue, kTimerManagerCID, &rv); + if (NS_FAILED(rv)) return rv; + + do { + // Give priority to system messages (in particular keyboard, mouse, + // timer, and paint messages). + if (::PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) || + ::PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || + ::PeekMessage(&msg, NULL, 0, WM_USER-1, PM_REMOVE) || + ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + + gotMessage = true; + + // process timer queue. + } else if (queue->HasReadyTimers(NS_PRIORITY_LOWEST)) { + + do { + queue->FireNextReadyTimer(NS_PRIORITY_LOWEST); + } while (queue->HasReadyTimers(NS_PRIORITY_LOWEST) && + !::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)); + + } else { + // Block and wait for any posted application message + ::WaitMessage(); + } + + } while (!gotMessage); + #ifdef DEBUG_danm if (msg.message != WM_TIMER) printf("-> %d", msg.message); #endif - if (isOK) { //#ifdef MOZ_AIMM // not need? // if (!nsToolkit::gAIMMMsgPumpOwner || (nsToolkit::gAIMMMsgPumpOwner->OnTranslateMessage(&msg) != S_OK)) //#endif - TranslateMessage(&msg); - aEvent = &msg; - aRealEvent = PR_TRUE; - return NS_OK; - } - aRealEvent = PR_FALSE; - return NS_ERROR_FAILURE; + TranslateMessage(&msg); + aEvent = &msg; + aRealEvent = PR_TRUE; + return NS_OK; } nsresult nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent) diff --git a/mozilla/widget/src/windows/nsLookAndFeel.cpp b/mozilla/widget/src/windows/nsLookAndFeel.cpp index 703dda3512a..7b8212a6a2c 100644 --- a/mozilla/widget/src/windows/nsLookAndFeel.cpp +++ b/mozilla/widget/src/windows/nsLookAndFeel.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Michael Lowe */ #include "nsLookAndFeel.h" @@ -238,6 +239,40 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_CaretWidthTwips: aMetric = 30; break; + case eMetric_SubmenuDelay: + { + static PRInt32 sSubmenuDelay = -1; + + if (sSubmenuDelay == -1) { + HKEY key; + char value[100]; + DWORD length, type; + LONG result; + + sSubmenuDelay = 200; + + result = ::RegOpenKeyEx(HKEY_CURRENT_USER, + "Control Panel\\Desktop", 0, KEY_READ, &key); + + if (result == ERROR_SUCCESS) { + length = sizeof(value); + + result = ::RegQueryValueEx(key, "MenuShowDelay", + NULL, &type, (LPBYTE)&value, &length); + + ::RegCloseKey(key); + + PRInt32 errorCode; + nsString str(value); + PRInt32 submenuDelay = str.ToInteger(&errorCode); + if (errorCode == NS_OK) { + sSubmenuDelay = submenuDelay; + } + } + } + aMetric = sSubmenuDelay; + } + break; default: aMetric = -1; res = NS_ERROR_FAILURE; diff --git a/mozilla/widget/src/windows/nsWindow.cpp b/mozilla/widget/src/windows/nsWindow.cpp index afca1b7bcfb..9b2462aac90 100644 --- a/mozilla/widget/src/windows/nsWindow.cpp +++ b/mozilla/widget/src/windows/nsWindow.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Michael Lowe */ #if defined(DEBUG_ftang) @@ -69,8 +70,12 @@ #include "nsIClipboard.h" #include "nsWidgetsCID.h" +#include "nsITimer.h" +#include "nsITimerQueue.h" + static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); static NS_DEFINE_IID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID); +static NS_DEFINE_CID(kTimerManagerCID, NS_TIMERMANAGER_CID); BOOL nsWindow::sIsRegistered = FALSE; @@ -617,7 +622,6 @@ nsWindow::IsScrollbar(HWND aWnd) { //------------------------------------------------------------------------- LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - // check to see if we have a rollup listener registered if (nsnull != gRollupListener && nsnull != gRollupWidget) { @@ -2567,6 +2571,24 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT DispatchStandardEvent(NS_DISPLAYCHANGED); break; + case WM_ENTERIDLE: + { + nsresult rv; + NS_WITH_SERVICE(nsITimerQueue, queue, kTimerManagerCID, &rv); + if (!NS_FAILED(rv)) { + + if (queue->HasReadyTimers(NS_PRIORITY_LOWEST)) { + + MSG wmsg; + do { + //printf("fire\n"); + queue->FireNextReadyTimer(NS_PRIORITY_LOWEST); + } while (queue->HasReadyTimers(NS_PRIORITY_LOWEST) && + !::PeekMessage(&wmsg, NULL, 0, 0, PM_NOREMOVE)); + } + } + } + break; case WM_NOTIFY: // TAB change diff --git a/mozilla/widget/src/xlib/nsLookAndFeel.cpp b/mozilla/widget/src/xlib/nsLookAndFeel.cpp index 9cc147b0f0e..3ca5382e979 100644 --- a/mozilla/widget/src/xlib/nsLookAndFeel.cpp +++ b/mozilla/widget/src/xlib/nsLookAndFeel.cpp @@ -108,6 +108,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric) case eMetric_CaretWidthTwips: aMetric = 20; break; + case eMetric_SubmenuDelay: + aMetric = 200; + break; default: aMetric = -1; res = NS_ERROR_FAILURE; diff --git a/mozilla/widget/timer/public/makefile.win b/mozilla/widget/timer/public/makefile.win index 15f8047459a..1ab1b6a064a 100644 --- a/mozilla/widget/timer/public/makefile.win +++ b/mozilla/widget/timer/public/makefile.win @@ -25,6 +25,7 @@ DEPTH=..\..\.. EXPORTS = \ nsITimer.h \ nsITimerCallback.h \ + nsITimerQueue.h \ $(NULL) MODULE=timer diff --git a/mozilla/widget/timer/public/nsITimer.h b/mozilla/widget/timer/public/nsITimer.h index b1bed7a2b08..40f53142b6d 100644 --- a/mozilla/widget/timer/public/nsITimer.h +++ b/mozilla/widget/timer/public/nsITimer.h @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Michael Lowe */ #ifndef nsITimer_h___ #define nsITimer_h___ @@ -42,6 +43,36 @@ typedef void { 0x497eed20, 0xb740, 0x11d1, \ { 0x9b, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } } +// --- Timer priorities --- +#define NS_PRIORITY_HIGHEST 10 +#define NS_PRIORITY_HIGH 8 +#define NS_PRIORITY_NORMAL 5 +#define NS_PRIORITY_LOW 2 +#define NS_PRIORITY_LOWEST 0 + +// --- Timer types --- +#define NS_TYPE_ONE_SHOT 0 // Timer which fires once only + +#define NS_TYPE_REPEATING_SLACK 1 // After firing, timer is stopped and not + // restarted until notifcation routine completes. + // Specified timer period will be at least time between + // when processing for last firing notifcation completes + // and when the next firing occurs. This is the preferable + // repeating type for most situations. + +#define NS_TYPE_REPEATING_PRECISE 2 // Timer which aims to have constant time between firings. + // The processing time for each timer notification should + // not influence timer period. However, if the processing + // for the last timer firing could not be completed until + // just before the next firing occurs, then you could have + // two timer notification routines being executed in quick + // sucession. + +// --- Indicate if timers on your platform support repeating timers --- +#if defined(XP_PC) || defined(XP_UNIX) +#define REPEATING_TIMERS 1 +#endif + /** * Timer class, used to invoke a function or method after a fixed * millisecond interval. Note that this interface is subject to @@ -58,14 +89,17 @@ public: * * @param aFunc - The function to invoke * @param aClosure - an opaque pointer to pass to that function - * @param aRepeat - (Not yet implemented) One-shot or repeating * @param aDelay - The millisecond interval + * @param aPriority - The timer priority + * @param aType - The timer type : one shot or repeating * @result - NS_OK if this operation was successful */ - virtual nsresult Init(nsTimerCallbackFunc aFunc, - void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay)=0; + NS_IMETHOD Init(nsTimerCallbackFunc aFunc, + void *aClosure, + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + )=0; /** * Initialize a timer to fire after the given millisecond interval. @@ -73,25 +107,34 @@ public: * The Notify method of this method is invoked. * * @param aCallback - The interface to notify - * @param aRepeat - (Not yet implemented) One-shot or repeating * @param aDelay - The millisecond interval + * @param aPriority - The timer priority + * @param aType - The timer type : one shot or repeating * @result - NS_OK if this operation was successful */ - virtual nsresult Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay)=0; + NS_IMETHOD Init(nsITimerCallback *aCallback, + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + )=0; /// Cancels the timeout - virtual void Cancel()=0; + NS_IMETHOD_(void) Cancel()=0; /// @return the millisecond delay of the timeout - virtual PRUint32 GetDelay()=0; + NS_IMETHOD_(PRUint32) GetDelay()=0; /// Change the millisecond interval for the timeout - virtual void SetDelay(PRUint32 aDelay)=0; + NS_IMETHOD_(void) SetDelay(PRUint32 aDelay)=0; + + NS_IMETHOD_(PRUint32) GetPriority()=0; + NS_IMETHOD_(void) SetPriority(PRUint32 aPriority)=0; + + NS_IMETHOD_(PRUint32) GetType()=0; + NS_IMETHOD_(void) SetType(PRUint32 aType)=0; /// @return the opaque pointer - virtual void* GetClosure()=0; + NS_IMETHOD_(void*) GetClosure()=0; }; // @@ -101,8 +144,6 @@ public: // the intention is that it be linked statically with the library/DLL // or app that uses it. -extern -nsresult NS_NewTimer(nsITimer** aInstancePtrResult); +extern nsresult NS_NewTimer(nsITimer** aInstancePtrResult); #endif // nsITimer_h___ - diff --git a/mozilla/widget/timer/public/nsITimerCallback.h b/mozilla/widget/timer/public/nsITimerCallback.h index e25badbb47d..4da00bd7559 100644 --- a/mozilla/widget/timer/public/nsITimerCallback.h +++ b/mozilla/widget/timer/public/nsITimerCallback.h @@ -41,7 +41,7 @@ class nsITimerCallback : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITIMERCALLBACK_IID) - virtual void Notify(nsITimer *timer) = 0; + NS_IMETHOD_(void) Notify(nsITimer *timer) = 0; }; #endif diff --git a/mozilla/widget/timer/src/beos/nsTimer.cpp b/mozilla/widget/timer/src/beos/nsTimer.cpp index 48072f32fb8..f2dd5e58a5a 100644 --- a/mozilla/widget/timer/src/beos/nsTimer.cpp +++ b/mozilla/widget/timer/src/beos/nsTimer.cpp @@ -91,20 +91,29 @@ public: TimerImpl(); virtual ~TimerImpl(); - virtual nsresult Init(nsTimerCallbackFunc aFunc, - void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay); - - virtual nsresult Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay); + virtual nsresult Init(nsTimerCallbackFunc aFunc, + void *aClosure, + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); + + virtual nsresult Init(nsITimerCallback *aCallback, + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); NS_DECL_ISUPPORTS virtual void Cancel(); virtual PRUint32 GetDelay() { return mDelay; } virtual void SetDelay(PRUint32); + virtual PRUint32 GetPriority() {} + virtual void SetPriority(PRUint32 aPriority) {} + + virtual PRUint32 GetType() {} + virtual void SetType(PRUint32 aType) {} virtual void* GetClosure() { return mClosure; } void FireTimeout(); @@ -302,8 +311,7 @@ void TimerImpl::SetDelay(PRUint32 aDelay) } nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc, void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay) + PRUint32 aDelay, PRUint32 aPriority, PRUint32 aType) { mFunc = aFunc; mClosure = aClosure; @@ -313,8 +321,7 @@ nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc, void *aClosure, } nsresult TimerImpl::Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay) + PRUint32 aDelay, PRUint32 aPriority, PRUint32 aType) { mCallback = aCallback; NS_ADDREF(mCallback); diff --git a/mozilla/widget/timer/src/mac/nsTimer.cpp b/mozilla/widget/timer/src/mac/nsTimer.cpp index 395884f0b74..89ff5279933 100644 --- a/mozilla/widget/timer/src/mac/nsTimer.cpp +++ b/mozilla/widget/timer/src/mac/nsTimer.cpp @@ -72,17 +72,28 @@ class TimerImpl : public nsITimer virtual nsresult Init(nsTimerCallbackFunc aFunc, void *aClosure, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); virtual nsresult Init(nsITimerCallback *aCallback, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); virtual void Cancel(); virtual PRUint32 GetDelay(); - virtual void SetDelay(PRUint32 aDelay); + virtual PRUint32 GetPriority() {}; + virtual void SetPriority(PRUint32 aPriority) {}; + + virtual PRUint32 GetType() {}; + virtual void SetType(PRUint32 aType) {}; + virtual void* GetClosure(); #if DEBUG @@ -169,8 +180,11 @@ TimerImpl::~TimerImpl() //---------------------------------------------------------------------------------------- nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc, - void *aClosure, - PRUint32 aDelay) + void *aClosure, + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) //---------------------------------------------------------------------------------------- { mCallbackFunc = aFunc; @@ -181,7 +195,10 @@ nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc, //---------------------------------------------------------------------------------------- nsresult TimerImpl::Init(nsITimerCallback *aCallback, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) //---------------------------------------------------------------------------------------- { NS_ADDREF(aCallback); diff --git a/mozilla/widget/timer/src/os2/nsTimerOS2.cpp b/mozilla/widget/timer/src/os2/nsTimerOS2.cpp index 90b68a3db9f..fe6a0cd4132 100644 --- a/mozilla/widget/timer/src/os2/nsTimerOS2.cpp +++ b/mozilla/widget/timer/src/os2/nsTimerOS2.cpp @@ -100,7 +100,8 @@ nsTimer::~nsTimer() } nsresult nsTimer::Init( nsTimerCallbackFunc aFunc, - void *aClosure, PRUint32 aDelay) + void *aClosure, + PRUint32 aDelay, PRUint32 aPriority, PRUint32 aType) { mFunc = aFunc; mClosure = aClosure; @@ -108,7 +109,8 @@ nsresult nsTimer::Init( nsTimerCallbackFunc aFunc, return mManager->InitTimer( this, aDelay); } -nsresult nsTimer::Init( nsITimerCallback *aCallback, PRUint32 aDelay) +nsresult nsTimer::Init( nsITimerCallback *aCallback, PRUint32 aDelay, + PRUint32 aPriority, PRUint32 aType) { mCallback = aCallback; NS_ADDREF(mCallback); // this is daft, but test14 traps without it diff --git a/mozilla/widget/timer/src/os2/nsTimerOS2.h b/mozilla/widget/timer/src/os2/nsTimerOS2.h index cba33e2c6f7..ba6331a69d0 100644 --- a/mozilla/widget/timer/src/os2/nsTimerOS2.h +++ b/mozilla/widget/timer/src/os2/nsTimerOS2.h @@ -47,11 +47,23 @@ class nsTimer : public nsITimer void Construct(); void Destruct(); - nsresult Init( nsTimerCallbackFunc aFunc, void *aClosure, PRUint32 aDelay); - nsresult Init( nsITimerCallback *aCallback, PRUint32 aDelay); + nsresult Init( nsTimerCallbackFunc aFunc, void *aClosure, + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); + nsresult Init( nsITimerCallback *aCallback, PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); void Cancel(); PRUint32 GetDelay() { return mDelay; } void SetDelay( PRUint32 aDelay) {}; // XXX Windows does this too... + virtual PRUint32 GetPriority() {} + virtual void SetPriority(PRUint32 aPriority) {} + + virtual PRUint32 GetType() {} + virtual void SetType(PRUint32 aType) {} void *GetClosure() { return mClosure; } // Implementation diff --git a/mozilla/widget/timer/src/photon/nsTimer.cpp b/mozilla/widget/timer/src/photon/nsTimer.cpp index 50dc0e9dff8..8ff7268fbce 100644 --- a/mozilla/widget/timer/src/photon/nsTimer.cpp +++ b/mozilla/widget/timer/src/photon/nsTimer.cpp @@ -49,11 +49,26 @@ public: NS_DECL_ISUPPORTS - virtual nsresult Init( nsTimerCallbackFunc aFunc, void *aClosure, PRUint32 aDelay ); - virtual nsresult Init( nsITimerCallback *aCallback, PRUint32 aDelay ); + virtual nsresult Init(nsTimerCallbackFunc aFunc, + void *aClosure, + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); + + virtual nsresult Init(nsITimerCallback *aCallback, + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); + virtual void Cancel(); virtual PRUint32 GetDelay() { return mDelay; } virtual void SetDelay( PRUint32 aDelay ) { mDelay=aDelay; }; + virtual PRUint32 GetPriority() {} + virtual void SetPriority(PRUint32 aPriority) {} + virtual PRUint32 GetType() {} + virtual void SetType(PRUint32 aType) {} virtual void* GetClosure() { return mClosure; } static int TimerEventHandler( void *aData, pid_t aRcvId, void *aMsg, size_t aMsgLen ); @@ -155,7 +170,8 @@ NS_METHOD TimerImpl::SetupTimer( PRUint32 aDelay ) } -NS_METHOD TimerImpl::Init( nsTimerCallbackFunc aFunc, void *aClosure, PRUint32 aDelay ) +NS_METHOD TimerImpl::Init( nsTimerCallbackFunc aFunc, void *aClosure, + PRUint32 aDelay, PRUint32 aPriority, PRUint32 aType) { nsresult err; @@ -166,7 +182,8 @@ NS_METHOD TimerImpl::Init( nsTimerCallbackFunc aFunc, void *aClosure, PRUint32 a } -NS_METHOD TimerImpl::Init( nsITimerCallback *aCallback, PRUint32 aDelay ) +NS_METHOD TimerImpl::Init( nsITimerCallback *aCallback, PRUint32 aDelay, + PRUint32 aPriority, PRUint32 aType) { nsresult err; diff --git a/mozilla/widget/timer/src/rhapsody/nsTimer.cpp b/mozilla/widget/timer/src/rhapsody/nsTimer.cpp index 723b6b7bbae..cb0a1229448 100644 --- a/mozilla/widget/timer/src/rhapsody/nsTimer.cpp +++ b/mozilla/widget/timer/src/rhapsody/nsTimer.cpp @@ -63,18 +63,30 @@ public: virtual nsresult Init(nsTimerCallbackFunc aFunc, void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); virtual nsresult Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); NS_DECL_ISUPPORTS virtual void Cancel(); + virtual PRUint32 GetDelay() { return mDelay; } virtual void SetDelay(PRUint32 aDelay) { mDelay=aDelay; }; + + virtual PRUint32 GetPriority() {} + virtual void SetPriority(PRUint32 aPriority) {} + + virtual PRUint32 GetType() {} + virtual void SetType(PRUint32 aType) {} + virtual void* GetClosure() { return mClosure; } void FireTimeout(); @@ -125,8 +137,10 @@ TimerImpl::~TimerImpl() nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc, void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { mFunc = aFunc; mClosure = aClosure; @@ -143,8 +157,10 @@ TimerImpl::Init(nsTimerCallbackFunc aFunc, nsresult TimerImpl::Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { mCallback = aCallback; // mRepeat = aRepeat; diff --git a/mozilla/widget/timer/src/unix/gtk/nsTimerGtk.cpp b/mozilla/widget/timer/src/unix/gtk/nsTimerGtk.cpp index 69c20033228..8dda54abbf1 100644 --- a/mozilla/widget/timer/src/unix/gtk/nsTimerGtk.cpp +++ b/mozilla/widget/timer/src/unix/gtk/nsTimerGtk.cpp @@ -17,7 +17,8 @@ * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Alexander Larsson (alla@lysator.liu.se) */ #include "nsTimerGtk.h" @@ -27,10 +28,22 @@ static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID); // extern "C" int NS_TimeToNextTimeout(struct timeval *aTimer); // extern "C" void NS_ProcessTimeouts(void); -extern "C" gint nsTimerExpired(gpointer aCallData); +extern "C" gboolean nsTimerExpired(gpointer aCallData); -void nsTimerGtk::FireTimeout() +/* Just linear interpolation. Is this good? */ +static gint calc_priority(PRUint32 aPriority) { + int pri = ((G_PRIORITY_HIGH-G_PRIORITY_LOW)*(int)aPriority)/NS_PRIORITY_HIGHEST + G_PRIORITY_LOW; + return pri; +} + +PRBool nsTimerGtk::FireTimeout() +{ + if (mType == NS_TYPE_REPEATING_PRECISE) { + mTimerId = g_timeout_add_full(calc_priority(mPriority), + mDelay, nsTimerExpired, this, NULL); + } + if (mFunc != NULL) { (*mFunc)(this, mClosure); } @@ -38,12 +51,38 @@ void nsTimerGtk::FireTimeout() mCallback->Notify(this); // Fire the timer } -// Always repeating here - -// if (mRepeat) -// mTimerId = gtk_timeout_add(aDelay, nsTimerExpired, this); + return (mType == NS_TYPE_REPEATING_SLACK); } +void nsTimerGtk::SetDelay(PRUint32 aDelay) +{ + if (aDelay!=mDelay) { + Cancel(); + mDelay=aDelay; + mTimerId = g_timeout_add_full(calc_priority(mPriority), + mDelay, nsTimerExpired, this, NULL); + } +}; + +void nsTimerGtk::SetPriority(PRUint32 aPriority) +{ + if (aPriority!=mPriority) { + Cancel(); + mPriority = aPriority; + mTimerId = g_timeout_add_full(calc_priority(mPriority), + mDelay, nsTimerExpired, this, NULL); + } +} + +void nsTimerGtk::SetType(PRUint32 aType) +{ + if (aType!=mType) { + Cancel(); + mType = aType; + mTimerId = g_timeout_add_full(calc_priority(mPriority), + mDelay, nsTimerExpired, this, NULL); + } +} nsTimerGtk::nsTimerGtk() { @@ -55,11 +94,12 @@ nsTimerGtk::nsTimerGtk() mTimerId = 0; mDelay = 0; mClosure = NULL; + mPriority = 0; + mType = NS_TYPE_ONE_SHOT; } nsTimerGtk::~nsTimerGtk() { - // printf("nsTimerGtk::~nsTimerGtk called for %p\n", this); Cancel(); @@ -68,91 +108,61 @@ nsTimerGtk::~nsTimerGtk() nsresult nsTimerGtk::Init(nsTimerCallbackFunc aFunc, - void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay) + void *aClosure, + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { //printf("nsTimerGtk::Init called with func + closure for %p\n", this); mFunc = aFunc; mClosure = aClosure; - // mRepeat = aRepeat; + mPriority = aPriority; + mType = aType; + mDelay = aDelay; -// This is ancient debug code that is making it impossible to have timeouts -// greater than 10 seconds. -re - -// if ((aDelay > 10000) || (aDelay < 0)) { -// printf("Timer::Init() called with bogus value \"%d\"! Not enabling timer.\n", -// aDelay); -// return Init(aDelay); -// } - - mTimerId = gtk_timeout_add(aDelay, nsTimerExpired, this); - - return Init(aDelay); + mTimerId = g_timeout_add_full(calc_priority(mPriority), + mDelay, nsTimerExpired, this, NULL); + + return NS_OK; } nsresult nsTimerGtk::Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { //printf("nsTimerGtk::Init called with callback only for %p\n", this); mCallback = aCallback; NS_ADDREF(mCallback); - // mRepeat = aRepeat; - -// This is ancient debug code that is making it impossible to have timeouts -// greater than 10 seconds. -re - -// if ((aDelay > 10000) || (aDelay < 0)) { -// printf("Timer::Init() called with bogus value \"%d\"! Not enabling timer.\n", -// aDelay); -// return Init(aDelay); -// } - - mTimerId = gtk_timeout_add(aDelay, nsTimerExpired, this); - - return Init(aDelay); -} - -nsresult -nsTimerGtk::Init(PRUint32 aDelay) -{ - //printf("nsTimerGtk::Init called with delay %d only for %p\n", aDelay, this); - + mPriority = aPriority; + mType = aType; mDelay = aDelay; - // NS_ADDREF(this); + mTimerId = g_timeout_add_full(calc_priority(mPriority), + mDelay, nsTimerExpired, this, NULL); + return NS_OK; } NS_IMPL_ISUPPORTS(nsTimerGtk, kITimerIID) - void nsTimerGtk::Cancel() { //printf("nsTimerGtk::Cancel called for %p\n", this); - //nsTimerGtk *me = this; - if (mTimerId) - gtk_timeout_remove(mTimerId); - - // - // This is reported as a leak by purify, but it also causes a - // crash on startup if uncommented. Need to dig deeper. - // - //NS_RELEASE(me); - // + g_source_remove(mTimerId); } -gint nsTimerExpired(gpointer aCallData) +gboolean nsTimerExpired(gpointer aCallData) { //printf("nsTimerExpired for %p\n", aCallData); nsTimerGtk* timer = (nsTimerGtk *)aCallData; - timer->FireTimeout(); - return 0; + return timer->FireTimeout(); } #ifdef MOZ_MONOLITHIC_TOOLKIT diff --git a/mozilla/widget/timer/src/unix/gtk/nsTimerGtk.h b/mozilla/widget/timer/src/unix/gtk/nsTimerGtk.h index bcc785e344f..1df2989707c 100644 --- a/mozilla/widget/timer/src/unix/gtk/nsTimerGtk.h +++ b/mozilla/widget/timer/src/unix/gtk/nsTimerGtk.h @@ -40,30 +40,41 @@ public: virtual nsresult Init(nsTimerCallbackFunc aFunc, void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); virtual nsresult Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); NS_DECL_ISUPPORTS virtual void Cancel(); + virtual PRUint32 GetDelay() { return mDelay; } - virtual void SetDelay(PRUint32 aDelay) { mDelay=aDelay; }; + virtual void SetDelay(PRUint32 aDelay); + + virtual PRUint32 GetPriority() { return mPriority; } + virtual void SetPriority(PRUint32 aPriority); + + virtual PRUint32 GetType() { return mType; } + virtual void SetType(PRUint32 aType); + virtual void* GetClosure() { return mClosure; } - void FireTimeout(); + PRBool FireTimeout(); private: - nsresult Init(PRUint32 aDelay); - PRUint32 mDelay; + PRUint32 mPriority; + PRUint32 mType; nsTimerCallbackFunc mFunc; void * mClosure; nsITimerCallback * mCallback; - // PRBool mRepeat; nsTimerGtk * mNext; guint mTimerId; }; diff --git a/mozilla/widget/timer/src/unix/motif/nsTimerMotif.cpp b/mozilla/widget/timer/src/unix/motif/nsTimerMotif.cpp index d37dc5016c4..e5996c9439c 100644 --- a/mozilla/widget/timer/src/unix/motif/nsTimerMotif.cpp +++ b/mozilla/widget/timer/src/unix/motif/nsTimerMotif.cpp @@ -72,8 +72,10 @@ static NS_DEFINE_CID(kCMotifAppContextServiceCID, NS_MOTIF_APP_CONTEXT_SERVICE_C nsresult nsTimerMotif::Init(nsTimerCallbackFunc aFunc, void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { mFunc = aFunc; mClosure = aClosure; @@ -90,8 +92,10 @@ nsTimerMotif::Init(nsTimerCallbackFunc aFunc, nsresult nsTimerMotif::Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { mCallback = aCallback; // mRepeat = aRepeat; diff --git a/mozilla/widget/timer/src/unix/motif/nsTimerMotif.h b/mozilla/widget/timer/src/unix/motif/nsTimerMotif.h index aeea7449d91..ad4a67a4072 100644 --- a/mozilla/widget/timer/src/unix/motif/nsTimerMotif.h +++ b/mozilla/widget/timer/src/unix/motif/nsTimerMotif.h @@ -39,18 +39,30 @@ public: virtual nsresult Init(nsTimerCallbackFunc aFunc, void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); virtual nsresult Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); NS_DECL_ISUPPORTS virtual void Cancel(); + virtual PRUint32 GetDelay() { return mDelay; } virtual void SetDelay(PRUint32 aDelay) { mDelay=aDelay; }; + + virtual PRUint32 GetPriority() {} + virtual void SetPriority(PRUint32 aPriority) {} + + virtual PRUint32 GetType() {} + virtual void SetType(PRUint32 aType) {} + virtual void* GetClosure() { return mClosure; } void FireTimeout(); diff --git a/mozilla/widget/timer/src/unix/qt/nsTimerQt.cpp b/mozilla/widget/timer/src/unix/qt/nsTimerQt.cpp index b76ec4e0ff4..41df4218acf 100644 --- a/mozilla/widget/timer/src/unix/qt/nsTimerQt.cpp +++ b/mozilla/widget/timer/src/unix/qt/nsTimerQt.cpp @@ -64,8 +64,10 @@ nsTimerQt::~nsTimerQt() nsresult nsTimerQt::Init(nsTimerCallbackFunc aFunc, void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { //debug("nsTimerQt::Init called with func + closure with %u delay", aDelay); mFunc = aFunc; @@ -84,8 +86,10 @@ nsTimerQt::Init(nsTimerCallbackFunc aFunc, nsresult nsTimerQt::Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { //debug("nsTimerQt::Init called with callback only with %u delay", aDelay); mCallback = aCallback; diff --git a/mozilla/widget/timer/src/unix/qt/nsTimerQt.h b/mozilla/widget/timer/src/unix/qt/nsTimerQt.h index 38f6a1bead4..cfa7ca31fa4 100644 --- a/mozilla/widget/timer/src/unix/qt/nsTimerQt.h +++ b/mozilla/widget/timer/src/unix/qt/nsTimerQt.h @@ -38,19 +38,31 @@ public: virtual ~nsTimerQt(); virtual nsresult Init(nsTimerCallbackFunc aFunc, - void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay); - + void *aClosure, + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); + virtual nsresult Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); NS_DECL_ISUPPORTS virtual void Cancel(); + virtual PRUint32 GetDelay() { return mDelay; } virtual void SetDelay(PRUint32 aDelay) { mDelay=aDelay; }; + + virtual PRUint32 GetPriority() {} + virtual void SetPriority(PRUint32 aPriority) {} + + virtual PRUint32 GetType() {} + virtual void SetType(PRUint32 aType) {} + virtual void* GetClosure() { return mClosure; } void FireTimeout(); diff --git a/mozilla/widget/timer/src/unix/xlib/nsTimerXlib.cpp b/mozilla/widget/timer/src/unix/xlib/nsTimerXlib.cpp index 7de27b360bb..002406b6fc4 100644 --- a/mozilla/widget/timer/src/unix/xlib/nsTimerXlib.cpp +++ b/mozilla/widget/timer/src/unix/xlib/nsTimerXlib.cpp @@ -70,7 +70,10 @@ NS_IMPL_ISUPPORTS(nsTimerXlib, kITimerIID) nsresult nsTimerXlib::Init(nsTimerCallbackFunc aFunc, void *aClosure, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { mFunc = aFunc; mClosure = aClosure; @@ -79,7 +82,10 @@ nsTimerXlib::Init(nsTimerCallbackFunc aFunc, nsresult nsTimerXlib::Init(nsITimerCallback *aCallback, - PRUint32 aDelay) + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { mCallback = aCallback; NS_ADDREF(mCallback); diff --git a/mozilla/widget/timer/src/unix/xlib/nsTimerXlib.h b/mozilla/widget/timer/src/unix/xlib/nsTimerXlib.h index 988932270fc..441fa14e866 100644 --- a/mozilla/widget/timer/src/unix/xlib/nsTimerXlib.h +++ b/mozilla/widget/timer/src/unix/xlib/nsTimerXlib.h @@ -39,11 +39,17 @@ public: virtual ~nsTimerXlib(); virtual nsresult Init(nsTimerCallbackFunc aFunc, - void *aClosure, - PRUint32 aDelay); + void *aClosure, + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); virtual nsresult Init(nsITimerCallback *aCallback, - PRUint32 aDelay); + PRUint32 aDelay, + PRUint32 aPriority = NS_PRIORITY_NORMAL, + PRUint32 aType = NS_TYPE_ONE_SHOT + ); NS_DECL_ISUPPORTS @@ -52,6 +58,13 @@ public: virtual PRUint32 GetDelay() { return 0; }; virtual void SetDelay(PRUint32 aDelay) {}; + + virtual PRUint32 GetPriority() {} + virtual void SetPriority(PRUint32 aPriority) {} + + virtual PRUint32 GetType() {} + virtual void SetType(PRUint32 aType) {} + virtual void *GetClosure() { return mClosure; } // this needs to be public so that the mainloop can diff --git a/mozilla/widget/timer/src/windows/makefile.win b/mozilla/widget/timer/src/windows/makefile.win index 2a7f8d8ae3c..57d51f2a100 100644 --- a/mozilla/widget/timer/src/windows/makefile.win +++ b/mozilla/widget/timer/src/windows/makefile.win @@ -24,8 +24,12 @@ LIBRARY_NAME=timer_s DEFINES=-DWIN32_LEAN_AND_MEAN -DSTRICT +EXPORTS=nsTimerManager.h nsWindowsTimer.h nsIWindowsTimerMap.h + CPPSRCS = \ nsTimer.cpp \ + nsNewTimer.cpp \ + nsTimerManager.cpp \ $(NULL) MODULE=timer @@ -34,6 +38,8 @@ REQUIRES=xpcom CPP_OBJS= \ .\$(OBJDIR)\nsTimer.obj \ + .\$(OBJDIR)\nsNewTimer.obj \ + .\$(OBJDIR)\nsTimerManager.obj \ $(NULL) LINCS= \ diff --git a/mozilla/widget/timer/src/windows/nsTimer.cpp b/mozilla/widget/timer/src/windows/nsTimer.cpp index 730c4619115..6328a10f95e 100644 --- a/mozilla/widget/timer/src/windows/nsTimer.cpp +++ b/mozilla/widget/timer/src/windows/nsTimer.cpp @@ -18,349 +18,236 @@ * Rights Reserved. * * Contributor(s): + * Michael Lowe */ -#include "nsITimer.h" -#include "nsITimerCallback.h" + +#include "nsWindowsTimer.h" +#include "nsITimerQueue.h" +#include "nsIWindowsTimerMap.h" #include "nsCRT.h" #include "prlog.h" #include #include #include +#include "nsWidgetsCID.h" +#include "nsIServiceManager.h" +#include -static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID); -/* - * Implementation of timers lifted from Windows front-end file timer.cpp - */ -class TimerImpl : public nsITimer { -public: - static TimerImpl *gTimerList; - static UINT gWindowsTimer; - static DWORD gNextFire; +static NS_DEFINE_CID(kTimerManagerCID, NS_TIMERMANAGER_CID); - static void ProcessTimeouts(DWORD aNow); - static void SyncTimeoutPeriod(DWORD aTickCount); -public: - TimerImpl(); - virtual ~TimerImpl(); +class nsTimer; - virtual nsresult Init(nsTimerCallbackFunc aFunc, - void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay); - virtual nsresult Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay); +#define NS_PRIORITY_IMMEDIATE 10 - NS_DECL_ISUPPORTS - - virtual void Cancel(); - void Fire(DWORD aNow); - - virtual PRUint32 GetDelay() { return mDelay; } - virtual void SetDelay(PRUint32 aDelay) {}; - - virtual void* GetClosure() { return mClosure; } - -private: - nsresult Init(PRUint32 aDelay); - - PRUint32 mDelay; - nsTimerCallbackFunc mFunc; - void *mClosure; - nsITimerCallback *mCallback; - DWORD mFireTime; - // PRBool mRepeat; - TimerImpl *mNext; -}; - -TimerImpl *TimerImpl::gTimerList = NULL; -UINT TimerImpl::gWindowsTimer = 0; -DWORD TimerImpl::gNextFire = (DWORD)-1; void CALLBACK FireTimeout(HWND aWindow, UINT aMessage, UINT aTimerID, DWORD aTime) { - static BOOL bCanEnter = TRUE; - // Don't allow old timer messages in here. - if(aMessage != WM_TIMER) { + if(aMessage != WM_TIMER) { PR_ASSERT(0); return; } - if(aTimerID != TimerImpl::gWindowsTimer) { + nsresult rv; + NS_WITH_SERVICE(nsIWindowsTimerMap, manager, kTimerManagerCID, &rv); + if (NS_FAILED(rv)) return; + + nsTimer* timer = manager->GetTimer(aTimerID); + if (timer == nsnull) { return; } - - // Block only one entry into this function, or else. - if(bCanEnter) { - bCanEnter = FALSE; - // see if we need to fork off any timeout functions - if(TimerImpl::gTimerList) { - TimerImpl::ProcessTimeouts(aTime); - } - bCanEnter = TRUE; + + if (timer->GetType() != NS_TYPE_REPEATING_PRECISE) { + // stop OS timer: may be restarted later + timer->KillOSTimer(); + } + + nsCOMPtr queue = do_QueryInterface(manager, &rv); + if (NS_FAILED(rv)) return; + + if (timer->GetPriority() >= NS_PRIORITY_IMMEDIATE) { + // fire timer immediatly + timer->Fire(); + + } else { + // defer timer firing + queue->AddReadyQueue(timer); + } + + // while event queue is empty, fire off waiting timers + MSG wmsg; + while (queue->HasReadyTimers(NS_PRIORITY_LOWEST) && + !::PeekMessage(&wmsg, NULL, 0, 0, PM_NOREMOVE)) { + queue->FireNextReadyTimer(NS_PRIORITY_LOWEST); } } -// Function to correctly have the timer be set. -void -TimerImpl::SyncTimeoutPeriod(DWORD aTickCount) + +NS_IMPL_ISUPPORTS1(nsTimer, nsITimer) + + +nsTimer::nsTimer() : nsITimer() { - // May want us to set tick count ourselves. - if(aTickCount == 0) { - aTickCount = ::GetTickCount(); - } + NS_INIT_ISUPPORTS(); - // If there's no list, we should clear the timer. - if(!gTimerList) { - if(gWindowsTimer) { - ::KillTimer(NULL, gWindowsTimer); - gWindowsTimer = 0; - gNextFire = (DWORD)-1; - } - } - else { - // See if we need to clear the current timer. - // Curcumstances are that if the timer will not - // fire on time for the next timeout. - BOOL bSetTimer = FALSE; - TimerImpl *pTimeout = gTimerList; - if(gWindowsTimer) { - if(pTimeout->mFireTime != gNextFire) { - ::KillTimer(NULL, gWindowsTimer); - gWindowsTimer = 0; - gNextFire = (DWORD)-1; - - // Set the timer. - bSetTimer = TRUE; - } - } - else { - // No timer set, attempt. - bSetTimer = TRUE; - } - - if(bSetTimer) { - DWORD dwFireWhen = pTimeout->mFireTime > aTickCount ? - pTimeout->mFireTime - aTickCount : 0; - if(dwFireWhen > UINT_MAX) { - dwFireWhen = UINT_MAX; - } - UINT uFireWhen = (UINT)dwFireWhen; - - PR_ASSERT(gWindowsTimer == 0); - gWindowsTimer = ::SetTimer(NULL, 0, uFireWhen, (TIMERPROC)FireTimeout); - - if(gWindowsTimer) { - // Set the fire time. - gNextFire = pTimeout->mFireTime; - } - } - } -} - -// Walk down the timeout list and launch anyone appropriate -void -TimerImpl::ProcessTimeouts(DWORD aNow) -{ - TimerImpl *p = gTimerList; - if(aNow == 0) { - aNow = ::GetTickCount(); - } - - BOOL bCalledSync = FALSE; - - // loop over all entries - while(p) { - // send it - if(p->mFireTime < aNow) { - // Make sure that the timer cannot be deleted during the - // Fire(...) call which may release *all* other references - // to p... - NS_ADDREF(p); - p->Fire(aNow); - - // Clear the timer. - // Period synced. - p->Cancel(); - bCalledSync = TRUE; - NS_RELEASE(p); - - // Reset the loop (can't look at p->pNext now, and called - // code may have added/cleared timers). - // (could do this by going recursive and returning). - p = gTimerList; - } else { - // Make sure we fire an timer. - // Also, we need to check to see if things are backing up (they - // may be asking to be fired long before we ever get to them, - // and we don't want to pass in negative values to the real - // timer code, or it takes days to fire.... - if(bCalledSync == FALSE) { - SyncTimeoutPeriod(aNow); - bCalledSync = TRUE; - } - // Get next timer. - p = p->mNext; - } - } -} - - -TimerImpl::TimerImpl() -{ - NS_INIT_REFCNT(); - mFunc = NULL; - mCallback = NULL; - mNext = NULL; + mFunc = nsnull; + mCallback = nsnull; mClosure = nsnull; + mTimerID = 0; + mTimerRunning = false; } -TimerImpl::~TimerImpl() + +nsTimer::~nsTimer() { - Cancel(); - NS_IF_RELEASE(mCallback); -} - -nsresult -TimerImpl::Init(nsTimerCallbackFunc aFunc, - void *aClosure, -// PRBool aRepeat, - PRUint32 aDelay) -{ - mFunc = aFunc; - mClosure = aClosure; - // mRepeat = aRepeat; - - return Init(aDelay); -} - -nsresult -TimerImpl::Init(nsITimerCallback *aCallback, -// PRBool aRepeat, - PRUint32 aDelay) -{ - mCallback = aCallback; - NS_ADDREF(mCallback); - // mRepeat = aRepeat; - - return Init(aDelay); -} - -nsresult -TimerImpl::Init(PRUint32 aDelay) -{ - DWORD dwNow = ::GetTickCount(); + KillOSTimer(); - mDelay = aDelay; - mFireTime = (DWORD) aDelay + dwNow; - mNext = NULL; - - // add it to the list - if(!gTimerList) { - // no list add it - gTimerList = this; - } - else { - - // is it before everything else on the list? - if(mFireTime < gTimerList->mFireTime) { - - mNext = gTimerList; - gTimerList = this; - - } else { - - TimerImpl * pPrev = gTimerList; - TimerImpl * pCurrent = gTimerList; - - while(pCurrent && (pCurrent->mFireTime <= mFireTime)) { - pPrev = pCurrent; - pCurrent = pCurrent->mNext; - } - - PR_ASSERT(pPrev); - - // insert it after pPrev (this could be at the end of the list) - mNext = pPrev->mNext; - pPrev->mNext = this; - - } - - } - - NS_ADDREF(this); - - // Sync the timer fire period. - SyncTimeoutPeriod(dwNow); - - return NS_OK; + NS_IF_RELEASE(mCallback); } -NS_IMPL_ISUPPORTS(TimerImpl, kITimerIID) -void -TimerImpl::Fire(DWORD aNow) +NS_IMETHODIMP_(void) nsTimer::SetPriority(PRUint32 aPriority) +{ + PR_ASSERT(aPriority >= NS_PRIORITY_LOWEST && + aPriority <= NS_PRIORITY_HIGHEST); + mPriority = aPriority; +} + + +NS_IMETHODIMP nsTimer::Init(nsTimerCallbackFunc aFunc, + void *aClosure, + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { - if (mFunc != NULL) { - (*mFunc)(this, mClosure); - } - else if (mCallback != NULL) { - mCallback->Notify(this); - } + mFunc = aFunc; + mClosure = aClosure; + + return Init(aDelay, aPriority, aType); } -void -TimerImpl::Cancel() + +NS_IMETHODIMP nsTimer::Init(nsITimerCallback *aCallback, + PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { - TimerImpl *me = this; + mCallback = aCallback; + NS_ADDREF(mCallback); - if(gTimerList == this) { - - // first element in the list lossage - gTimerList = mNext; - - } else { - - // walk until no next pointer - for(TimerImpl * p = gTimerList; p && p->mNext && (p->mNext != this); p = p->mNext) - ; - - // if we found something valid pull it out of the list - if(p && p->mNext && p->mNext == this) { - p->mNext = mNext; - - } else { - // get out before we delete something that looks bogus - return; - } - - } - - // if we got here it must have been a valid element so trash it - NS_RELEASE(me); - - // If there's now no be sure to clear the timer. - SyncTimeoutPeriod(0); + return Init(aDelay, aPriority, aType); } -nsresult NS_NewTimer(nsITimer** aInstancePtrResult) + +nsresult nsTimer::Init(PRUint32 aDelay, + PRUint32 aPriority, + PRUint32 aType + ) { - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } + // prevent timer being released before + // it has fired or is canceled + NS_ADDREF_THIS(); + mTimerRunning = true; - TimerImpl *timer = new TimerImpl(); - if (nsnull == timer) { - return NS_ERROR_OUT_OF_MEMORY; + mDelay = aDelay; + + SetPriority(aPriority); + SetType(aType); + + StartOSTimer(aDelay); + + return NS_OK; +} + + +void nsTimer::Fire() +{ + // prevent a canceled timer which is + // already in ready queue from firing + if (mTimerRunning == false) return; + + // prevent notification routine + // from releasing timer by canceling it + NS_ADDREF_THIS(); + + // invoke notification routine + if (mFunc != nsnull) { + (*mFunc)(this, mClosure); + } + else if (mCallback != nsnull) { + mCallback->Notify(this); + } + + if (GetType() == NS_TYPE_REPEATING_SLACK) { + // restart timer + StartOSTimer(GetDelay()); + + } else if (GetType() == NS_TYPE_ONE_SHOT) { + + // timer finished + if (mTimerRunning == true) { + mTimerRunning = false; + + NS_RELEASE_THIS(); + } + } + + NS_RELEASE_THIS(); +} + + +NS_IMETHODIMP_(void) nsTimer::Cancel() +{ + KillOSTimer(); + + // timer finished + if (mTimerRunning == true) { + mTimerRunning = false; + + NS_RELEASE_THIS(); + } +} + + +void nsTimer::StartOSTimer(PRUint32 aDelay) +{ + PR_ASSERT(mTimerID == 0); + + nsresult rv; + NS_WITH_SERVICE(nsIWindowsTimerMap, manager, kTimerManagerCID, &rv); + if (NS_FAILED(rv)) return; + + // create OS timer + mTimerID = ::SetTimer(NULL, 0, aDelay, (TIMERPROC)FireTimeout); + + // store mapping from OS timer to timer object + manager->AddTimer(mTimerID, this); +} + + +void nsTimer::KillOSTimer() +{ + if (mTimerID != 0) { + + nsresult rv; + NS_WITH_SERVICE(nsIWindowsTimerMap, manager, kTimerManagerCID, &rv); + + // remove mapping from OS timer to timer object + if (NS_SUCCEEDED(rv)) { + manager->RemoveTimer(mTimerID); } - return timer->QueryInterface(kITimerIID, (void **) aInstancePtrResult); + // kill OS timer + ::KillTimer(NULL, mTimerID); + + mTimerID = 0; + } } diff --git a/mozilla/xpfe/components/bookmarks/src/nsBookmarksService.cpp b/mozilla/xpfe/components/bookmarks/src/nsBookmarksService.cpp index e867537d27d..a6ef6fe7304 100644 --- a/mozilla/xpfe/components/bookmarks/src/nsBookmarksService.cpp +++ b/mozilla/xpfe/components/bookmarks/src/nsBookmarksService.cpp @@ -1794,7 +1794,7 @@ nsBookmarksService::Init() rv = NS_NewTimer(getter_AddRefs(mTimer)); if (NS_FAILED(rv)) return rv; - mTimer->Init(nsBookmarksService::FireTimer, this, /* repeat, */ BOOKMARK_TIMEOUT); + mTimer->Init(nsBookmarksService::FireTimer, this, BOOKMARK_TIMEOUT, NS_PRIORITY_LOWEST, NS_TYPE_REPEATING_SLACK); // Note: don't addref "this" as we'll cancel the timer in the nsBookmarkService destructor } @@ -2102,12 +2102,13 @@ else } #endif - +#ifndef REPEATING_TIMERS // reschedule the timer nsresult rv = NS_NewTimer(getter_AddRefs(bmks->mTimer)); if (NS_FAILED(rv)) return; bmks->mTimer->Init(nsBookmarksService::FireTimer, bmks, /* repeat, */ BOOKMARK_TIMEOUT); // Note: don't addref "bmks" as we'll cancel the timer in the nsBookmarkService destructor +#endif } @@ -2614,6 +2615,37 @@ nsBookmarksService::Release() } } + + + +NS_IMETHODIMP +nsBookmarksService::QueryInterface(REFNSIID aIID, void **aResult) +{ + NS_PRECONDITION(aResult != nsnull, "null ptr"); + if (! aResult) + return NS_ERROR_NULL_POINTER; + + if (aIID.Equals(NS_GET_IID(nsIBookmarksService)) || + aIID.Equals(kISupportsIID)) + { + *aResult = NS_STATIC_CAST(nsIBookmarksService*, this); + } + else if (aIID.Equals(NS_GET_IID(nsIRDFDataSource))) { + *aResult = NS_STATIC_CAST(nsIRDFDataSource*, this); + } + else if (aIID.Equals(NS_GET_IID(nsIRDFRemoteDataSource))) { + *aResult = NS_STATIC_CAST(nsIRDFRemoteDataSource*, this); + } + else { + *aResult = nsnull; + return NS_NOINTERFACE; + } + + NS_ADDREF(this); + return NS_OK; +} + + NS_IMPL_QUERY_INTERFACE6(nsBookmarksService, nsIBookmarksService, nsIRDFDataSource,