Fix bug 70243; yield more time to background applications when we're not busy. r=pinkerton, sr=waterson

This commit is contained in:
sfraser%netscape.com 2001-05-05 02:35:58 +00:00
Родитель 39361b75fa
Коммит 72df82543b
3 изменённых файлов: 158 добавлений и 114 удалений

Просмотреть файл

@ -187,6 +187,8 @@ nsMacMessagePump::nsMacMessagePump(nsToolkit *aToolkit, nsMacMessageSink* aSink)
mRunning = PR_FALSE;
mMouseRgn = ::NewRgn();
NS_ASSERTION(mToolkit, "No toolkit");
//
// create the TSM Message Pump
//
@ -257,44 +259,60 @@ void nsMacMessagePump::DoMessagePump()
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
// #define BUSINESS_INDICATOR
//#define BUSINESS_INDICATOR
#define kIdleHysterysisTicks 60
//=================================================================
/* Return TRUE if the program is busy, like doing network stuff.
*
*/
PRBool nsMacMessagePump::BrowserIsBusy()
{
{
// we avoid frenetic oscillations between busy and idle states by not going
// idle for a few ticks after we've detected idleness. This was added after
// observing rapid busy/idle oscillations during chrome loading.
static PRUint32 sNextIdleTicks = 0;
PRBool foundActivity = PR_TRUE;
do // convenience for breaking. We'll start by assuming that we're busy.
{
nsCOMPtr<nsISocketTransportService> socketTransport = do_GetService(kSocketTransportServiceCID);
if (socketTransport)
{
PRUint32 inUseTransports;
socketTransport->GetInUseTransportCount(&inUseTransports);
if (inUseTransports > 0)
break;
}
nsCOMPtr<nsIFileTransportService> fileTransport = do_GetService(kFileTransportServiceCID);
if (fileTransport)
{
PRUint32 inUseTransports;
fileTransport->GetInUseTransportCount(&inUseTransports);
if (inUseTransports > 0)
break;
}
if (mToolkit->ToolkitBusy())
break;
foundActivity = PR_FALSE;
} while(0);
PRBool isBusy = foundActivity;
if (foundActivity)
sNextIdleTicks = ::TickCount() + kIdleHysterysisTicks;
else if (::TickCount() < sNextIdleTicks)
isBusy = PR_TRUE;
#ifdef BUSINESS_INDICATOR
static PRBool wasBusy;
#endif
PRBool isBusy = PR_FALSE;
nsCOMPtr<nsISocketTransportService> socketTransport = do_GetService(kSocketTransportServiceCID);
if (socketTransport)
{
PRUint32 inUseTransports;
socketTransport->GetInUseTransportCount(&inUseTransports);
isBusy = inUseTransports > 0;
}
nsCOMPtr<nsIFileTransportService> fileTransport = do_GetService(kFileTransportServiceCID);
if (fileTransport)
{
PRUint32 inUseTransports;
fileTransport->GetInUseTransportCount(&inUseTransports);
isBusy |= (inUseTransports > 0);
}
#ifdef BUSINESS_INDICATOR
if (isBusy != wasBusy)
{
if (isBusy)
printf("¤¤ Message pump became busy\n");
else
printf("¤¤ Message pump became idle\n");
printf("¤¤ Message pump became %s at %ld (next idle %ld)\n", isBusy ? "busy" : "idle", ::TickCount(), sNextIdleTicks);
wasBusy = isBusy;
}
#endif
@ -322,19 +340,22 @@ PRBool nsMacMessagePump::GetEvent(EventRecord &theEvent)
// don't call more than once every 4 ticks
if (!havePendingEvent && (::TickCount() < sNextWNECall))
return PR_FALSE;
SInt32 sleepTime = (havePendingEvent || BrowserIsBusy()) ? 0 : 2;
// when in the background, we don't want to chew up time processing mouse move
// events, so set the mouse region to null. If we're in the fg, however,
// we want every mouseMove event we can get our grubby little hands on, so set
// it to a 1x1 rect.
RgnHandle mouseRgn = nsToolkit::IsAppInForeground() ? mMouseRgn : nsnull;
PRBool browserBusy = BrowserIsBusy();
SInt32 sleepTime = (havePendingEvent || browserBusy) ? 0 : 2;
::SetEventMask(everyEvent); // we need keyUp events
PRBool haveEvent = ::WaitNextEvent(everyEvent, &theEvent, sleepTime, mouseRgn);
sNextWNECall = ::TickCount() + kWNECallIntervalTicks;
// if we are not busy, call WNE as often as possible to yield time to
// other apps (especially important on Mac OS X)
sNextWNECall = browserBusy ? (::TickCount() + kWNECallIntervalTicks) : 0;
#if !TARGET_CARBON
if (haveEvent && ::TSMEvent(&theEvent) )

Просмотреть файл

@ -34,15 +34,13 @@
#include "nsIImageManager.h"
#include "nsGfxCIID.h"
//#define MAC_PL_EVENT_TWEAKING
// Class IDs...
static NS_DEFINE_CID(kEventQueueCID, NS_EVENTQUEUE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_IID(kImageManagerCID, NS_IMAGEMANAGER_CID);
static nsMacNSPREventQueueHandler* gEventQueueHandler = nsnull;
static nsMacNSPREventQueueHandler* gEventQueueHandler = nsnull;
//
// Static thread local storage index of the Toolkit
@ -55,7 +53,8 @@ static PRUintn gToolkitTLSIndex = 0;
//-------------------------------------------------------------------------
nsMacNSPREventQueueHandler::nsMacNSPREventQueueHandler(): Repeater()
{
mRefCnt = 0;
mRefCnt = 0;
mEventQueueService = do_GetService(kEventQueueServiceCID);
}
//-------------------------------------------------------------------------
@ -63,7 +62,7 @@ nsMacNSPREventQueueHandler::nsMacNSPREventQueueHandler(): Repeater()
//-------------------------------------------------------------------------
nsMacNSPREventQueueHandler::~nsMacNSPREventQueueHandler()
{
StopRepeating();
StopRepeating();
}
//-------------------------------------------------------------------------
@ -71,9 +70,9 @@ nsMacNSPREventQueueHandler::~nsMacNSPREventQueueHandler()
//-------------------------------------------------------------------------
void nsMacNSPREventQueueHandler::StartPumping()
{
++mRefCnt;
NS_LOG_ADDREF(this, mRefCnt, "nsMacNSPREventQueueHandler", sizeof(*this));
StartRepeating();
++mRefCnt;
NS_LOG_ADDREF(this, mRefCnt, "nsMacNSPREventQueueHandler", sizeof(*this));
StartRepeating();
}
//-------------------------------------------------------------------------
@ -81,16 +80,16 @@ void nsMacNSPREventQueueHandler::StartPumping()
//-------------------------------------------------------------------------
PRBool nsMacNSPREventQueueHandler::StopPumping()
{
if (mRefCnt > 0) {
--mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "nsMacNSPREventQueueHandler");
if (mRefCnt == 0) {
StopRepeating();
return PR_TRUE;
}
}
if (mRefCnt > 0) {
--mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "nsMacNSPREventQueueHandler");
if (mRefCnt == 0) {
StopRepeating();
return PR_TRUE;
}
}
return PR_FALSE;
return PR_FALSE;
}
//-------------------------------------------------------------------------
@ -98,7 +97,27 @@ PRBool nsMacNSPREventQueueHandler::StopPumping()
//-------------------------------------------------------------------------
void nsMacNSPREventQueueHandler::RepeatAction(const EventRecord& inMacEvent)
{
ProcessPLEventQueue();
ProcessPLEventQueue();
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
PRBool nsMacNSPREventQueueHandler::EventsArePending()
{
PRBool pendingEvents = PR_FALSE;
if (mEventQueueService)
{
nsCOMPtr<nsIEventQueue> queue;
mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
if (queue)
queue->PendingEvents(&pendingEvents);
}
return pendingEvents;
}
@ -107,35 +126,19 @@ void nsMacNSPREventQueueHandler::RepeatAction(const EventRecord& inMacEvent)
//-------------------------------------------------------------------------
void nsMacNSPREventQueueHandler::ProcessPLEventQueue()
{
nsCOMPtr<nsIEventQueueService> eventQService = do_GetService(kEventQueueServiceCID);
if (eventQService)
{
nsCOMPtr<nsIEventQueue> queue;
eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
#ifdef MAC_PL_EVENT_TWEAKING
// just handle one event at a time
if (queue)
{
PRBool plEventAvail = PR_FALSE;
queue->EventAvailable(plEventAvail);
if (plEventAvail)
{
PLEvent* thisEvent;
if (NS_SUCCEEDED(queue->GetEvent(&thisEvent)))
{
queue->HandleEvent(thisEvent);
}
}
}
#else
// the old way
if (queue)
queue->ProcessPendingEvents();
#endif
}
NS_ASSERTION(mEventQueueService, "Need event queue service here");
nsCOMPtr<nsIEventQueue> queue;
mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
if (queue)
{
PRBool eventsPending = PR_FALSE;
if (NS_SUCCEEDED(queue->PendingEvents(&eventsPending)) && eventsPending)
{
nsresult rv = queue->ProcessPendingEvents();
NS_ASSERTION(NS_SUCCEEDED(rv), "Error processing PLEvents");
}
}
}
@ -153,9 +156,9 @@ bool nsToolkit::sInForeground = true;
//-------------------------------------------------------------------------
nsToolkit::nsToolkit() : mInited(false)
{
NS_INIT_REFCNT();
if (gEventQueueHandler == nsnull)
gEventQueueHandler = new nsMacNSPREventQueueHandler;
NS_INIT_REFCNT();
if (gEventQueueHandler == nsnull)
gEventQueueHandler = new nsMacNSPREventQueueHandler;
}
//-------------------------------------------------------------------------
@ -165,17 +168,17 @@ nsToolkit::~nsToolkit()
{
nsWidgetAtoms::ReleaseAtoms();
/* StopPumping decrements a refcount on gEventQueueHandler; a prelude toward
stopping event handling. This is not something you want to do unless you've
bloody well started event handling and incremented the refcount. That's
done in the Init method, not the constructor, and that's what mInited is about.
*/
if (mInited && gEventQueueHandler) {
if (gEventQueueHandler->StopPumping()) {
delete gEventQueueHandler;
gEventQueueHandler = nsnull;
}
}
/* StopPumping decrements a refcount on gEventQueueHandler; a prelude toward
stopping event handling. This is not something you want to do unless you've
bloody well started event handling and incremented the refcount. That's
done in the Init method, not the constructor, and that's what mInited is about.
*/
if (mInited && gEventQueueHandler) {
if (gEventQueueHandler->StopPumping()) {
delete gEventQueueHandler;
gEventQueueHandler = nsnull;
}
}
// Remove the TLS reference to the toolkit...
PR_SetThreadPrivate(gToolkitTLSIndex, nsnull);
}
@ -186,40 +189,50 @@ nsToolkit::~nsToolkit()
//-------------------------------------------------------------------------
NS_IMETHODIMP nsToolkit::Init(PRThread */*aThread*/)
{
if (gEventQueueHandler)
gEventQueueHandler->StartPumping();
if (gEventQueueHandler)
gEventQueueHandler->StartPumping();
nsWidgetAtoms::AddRefAtoms();
mInited = true;
return NS_OK;
mInited = true;
return NS_OK;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
PRBool nsToolkit::ToolkitBusy()
{
return (gEventQueueHandler) ? gEventQueueHandler->EventsArePending() : PR_FALSE;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
bool nsToolkit::HasAppearanceManager()
{
#define APPEARANCE_MIN_VERSION 0x0110 // we require version 1.1
static bool inited = false;
static bool hasAppearanceManager = false;
#define APPEARANCE_MIN_VERSION 0x0110 // we require version 1.1
static bool inited = false;
static bool hasAppearanceManager = false;
if (inited)
return hasAppearanceManager;
inited = true;
if (inited)
return hasAppearanceManager;
inited = true;
SInt32 result;
if (::Gestalt(gestaltAppearanceAttr, &result) != noErr)
return false; // no Appearance Mgr
SInt32 result;
if (::Gestalt(gestaltAppearanceAttr, &result) != noErr)
return false; // no Appearance Mgr
if (::Gestalt(gestaltAppearanceVersion, &result) != noErr)
return false; // still version 1.0
if (::Gestalt(gestaltAppearanceVersion, &result) != noErr)
return false; // still version 1.0
hasAppearanceManager = (result >= APPEARANCE_MIN_VERSION);
hasAppearanceManager = (result >= APPEARANCE_MIN_VERSION);
return hasAppearanceManager;
return hasAppearanceManager;
}
@ -327,10 +340,10 @@ OSErr nsMacMemoryCushion::Init(Size bufferSize, Size reserveSize)
::HPurge(mBufferHandle);
#if !TARGET_CARBON
::SetGrowZone(NewGrowZoneProc(GrowZoneProc));
::SetGrowZone(NewGrowZoneProc(GrowZoneProc));
#endif
return noErr;
return noErr;
}

Просмотреть файл

@ -26,8 +26,10 @@
#include "nsIToolkit.h"
#include "nsRepeater.h"
class nsIEventQueue;
#include "nsCOMPtr.h"
class nsIEventQueue;
class nsIEventQueueService;
/**
* The toolkit abstraction is necessary because the message pump must
@ -66,6 +68,11 @@ public:
NS_IMETHOD Init(PRThread *aThread);
// are there pending events on the toolkit's event queue?
PRBool ToolkitBusy();
public:
// Appearance Mgr
static bool HasAppearanceManager();
@ -92,6 +99,8 @@ public:
// Repeater interface
virtual void RepeatAction(const EventRecord& inMacEvent);
PRBool EventsArePending();
protected:
void ProcessPLEventQueue();
@ -100,6 +109,7 @@ protected:
nsrefcnt mRefCnt;
nsCOMPtr<nsIEventQueueService> mEventQueueService;
};