зеркало из https://github.com/mozilla/pjs.git
Fix bug 70243; yield more time to background applications when we're not busy. r=pinkerton, sr=waterson
This commit is contained in:
Родитель
39361b75fa
Коммит
72df82543b
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче