diff --git a/mozilla/gfx/idl/Makefile.in b/mozilla/gfx/idl/Makefile.in index 7347957d163..47ffb787115 100644 --- a/mozilla/gfx/idl/Makefile.in +++ b/mozilla/gfx/idl/Makefile.in @@ -74,6 +74,10 @@ XPIDLSRCS += nsIPrintSettingsX.idl \ $(NULL) endif +ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) +XPIDLSRCS += nsIQDFlushManager.idl +endif + ifeq ($(MOZ_GFX_TOOLKIT),windows) XPIDLSRCS += nsIPrintSettingsWin.idl endif diff --git a/mozilla/gfx/idl/nsIQDFlushManager.idl b/mozilla/gfx/idl/nsIQDFlushManager.idl new file mode 100644 index 00000000000..8447ed8e5f2 --- /dev/null +++ b/mozilla/gfx/idl/nsIQDFlushManager.idl @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is supposed to avoid exccessive QuickDraw flushes. + * + * The Initial Developer of the Original Code is + * Mark Mentovai . + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +%{ C++ +#include +%} + +native CGrafPtr(CGrafPtr); +native RgnHandle(RgnHandle); + +/** + * nsIQDFlushManager is responsible for rate-limiting QuickDraw buffer + * flushes. Think of it as a plumber in a time of rationing. It's + * expected to be used as a singleton doled out by the service manager. + */ + +[uuid(40352CE3-9D15-4643-8CBF-71DA61650F13)] +interface nsIQDFlushManager : nsISupports +{ + /** + * Flushes the port buffer, a la QDFlushPortBuffer. If the buffer has + * been flushed too recently, the region to flush is instead added to + * the dirty region, and a buffer flush will be scheduled for an + * appropriate time. + * + * @param aPort the QuickDraw port to flush + * + * @param aRegion the region to flush or mark as dirty + */ + void flushPortBuffer(in CGrafPtr aPort, in RgnHandle aRegion); + + /** + * Cancels a pending flush scheduled by calling flushPortBuffer. This + * method is suitable to call when a port is destroyed. + * + * @param aPort the QuickDraw port to not flush + */ + void removePort(in CGrafPtr aPort); +}; diff --git a/mozilla/gfx/src/mac/nsGfxFactoryMac.cpp b/mozilla/gfx/src/mac/nsGfxFactoryMac.cpp index 48fcc729df6..1627c32730d 100644 --- a/mozilla/gfx/src/mac/nsGfxFactoryMac.cpp +++ b/mozilla/gfx/src/mac/nsGfxFactoryMac.cpp @@ -57,6 +57,9 @@ #include "nsCOMPtr.h" #include "nsUnicodeMappingUtil.h" #include "gfxImageFrame.h" +#ifdef MOZ_WIDGET_COCOA +#include "nsQDFlushManager.h" +#endif #include "nsIGenericFactory.h" @@ -76,6 +79,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsFontEnumeratorMac) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFontList) NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerMac) NS_GENERIC_FACTORY_CONSTRUCTOR(gfxImageFrame) +#ifdef MOZ_WIDGET_COCOA +NS_GENERIC_FACTORY_CONSTRUCTOR(nsQDFlushManager) +#endif static NS_IMETHODIMP nsScriptableRegionConstructor(nsISupports* aOuter, REFNSIID aIID, void** aResult) @@ -155,7 +161,13 @@ static const nsModuleComponentInfo components[] = { "windows image frame", GFX_IMAGEFRAME_CID, "@mozilla.org/gfx/image/frame;2", - gfxImageFrameConstructor, } + gfxImageFrameConstructor, }, +#ifdef MOZ_WIDGET_COCOA + { NS_QDFLUSHMANAGER_CLASSNAME, + NS_QDFLUSHMANAGER_CID, + NS_QDFLUSHMANAGER_CONTRACTID, + nsQDFlushManagerConstructor }, +#endif }; PR_STATIC_CALLBACK(void) diff --git a/mozilla/gfx/src/mac/nsQDFlushManager.cpp b/mozilla/gfx/src/mac/nsQDFlushManager.cpp index 8b47d0c2e2b..5b0c67255b5 100644 --- a/mozilla/gfx/src/mac/nsQDFlushManager.cpp +++ b/mozilla/gfx/src/mac/nsQDFlushManager.cpp @@ -38,77 +38,16 @@ #include "nsQDFlushManager.h" #include "nsComponentManagerUtils.h" -#include "nsIObserverService.h" #include "nsIServiceManager.h" #include "nsCRT.h" -class nsQDFlushPort : public nsITimerCallback -{ - // nsQDFlushManager is responsible for maintaining the list of port objects. - friend class nsQDFlushManager; - -protected: - nsQDFlushPort(CGrafPtr aPort); - ~nsQDFlushPort(); - - void Init(CGrafPtr aPort); - void Destroy(); - void FlushPortBuffer(RgnHandle aRegion); - PRInt64 TimeUntilFlush(AbsoluteTime aNow); - NS_DECL_ISUPPORTS - NS_DECL_NSITIMERCALLBACK - - // To use the display's refresh rate as the update Hz, see - // http://developer.apple.com/documentation/Performance/Conceptual/Drawing/Articles/FlushingContent.html . - // Here, use a hard-coded 30 Hz instead. - static const PRUint32 kRefreshRateHz = 30; // Maximum number of updates - // per second - - nsQDFlushPort* mNext; // Next object in list - CGrafPtr mPort; // Associated port - AbsoluteTime mLastFlushTime; // Last QDFlushPortBuffer call - nsCOMPtr mFlushTimer; // Timer for scheduled flush - PRPackedBool mFlushTimerRunning; // Is it? -}; - -class nsQDFlushObserver : public nsIObserver -{ - // nsQDFlushManager is responsible for creating the observer. - friend class nsQDFlushManager; - -protected: - nsQDFlushObserver(nsQDFlushManager* aParent); - ~nsQDFlushObserver(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - - nsQDFlushManager* mParent; // Parent object -}; - // nsQDFlushManager -// protected static -nsQDFlushManager* nsQDFlushManager::sQDFlushManager = nsnull; -nsQDFlushObserver* nsQDFlushManager::sQDFlushObserver = nsnull; - -// nsQDFlushManager() constructor -// -// If you create your own object, you are responsible for freeing it. Once -// freed, it will free the attached port objects. -// -// If you work through the static object by calling through the static -// sQDFlushPortBuffer method, the static object will be created dynamically -// at first call and will be freed automatically at shutdown. nsQDFlushManager::nsQDFlushManager() : mPortList(nsnull) { } -// ~nsQDFlushManager() destructor -// -// See the note about object creation and destruction in the comment -// preceding the constructor. nsQDFlushManager::~nsQDFlushManager() { nsQDFlushPort* port = mPortList; @@ -121,34 +60,6 @@ nsQDFlushManager::~nsQDFlushManager() } } -// FlushPortBuffer(aPort, aRegion) -// -// The public entry point for object-based calls. Calls -// QDFlushPortBuffer(aPort, aRegion) if aPort hasn't been flushed too -// recently. If it has been, calls QDAddRegionToDirtyRegion(aPort, aRegion) -// and if no flush has been scheduled, schedules a flush for the appropriate -// time. -// -// public -void -nsQDFlushManager::FlushPortBuffer(CGrafPtr aPort, RgnHandle aRegion) -{ - CreateOrGetPort(aPort)->FlushPortBuffer(aRegion); -} - -// sFlushPortBuffer(aPort, aRegion) -// -// The public entry point for calls into the static flush manager. Gets -// the static object, creating it if necessary, and then calls into -// FlushPortBuffer above. -// -// public static -void -nsQDFlushManager::sFlushPortBuffer(CGrafPtr aPort, RgnHandle aRegion) -{ - GetStaticQDFlushManager()->FlushPortBuffer(aPort, aRegion); -} - // CreateOrGetPort(aPort) // // Walks through the list of port objects and returns the one corresponding to @@ -203,15 +114,33 @@ nsQDFlushManager::CreateOrGetPort(CGrafPtr aPort) return port; } +NS_IMPL_ISUPPORTS1(nsQDFlushManager, nsIQDFlushManager) + +// nsIQDFlushManager implementation + +// FlushPortBuffer(aPort, aRegion) +// +// The public entry point for object-based calls. Calls +// QDFlushPortBuffer(aPort, aRegion) if aPort hasn't been flushed too +// recently. If it has been, calls QDAddRegionToDirtyRegion(aPort, aRegion) +// and if no flush has been scheduled, schedules a flush for the appropriate +// time. +// +// public +NS_IMETHODIMP +nsQDFlushManager::FlushPortBuffer(CGrafPtr aPort, RgnHandle aRegion) +{ + CreateOrGetPort(aPort)->FlushPortBuffer(aRegion); + return NS_OK; +} + // RemovePort(aPort) // // Walks through the list of port objects and removes the one corresponding to // aPort, if it exists. // -// Presently unused. -// -// protected -void +// public +NS_IMETHODIMP nsQDFlushManager::RemovePort(CGrafPtr aPort) { // Traversal is as in CreateOrGetPort. @@ -228,56 +157,11 @@ nsQDFlushManager::RemovePort(CGrafPtr aPort) // mPortList. That makes it easy to snip the old object out by // setting it to the follower. *portPtr = next; - return; + return NS_OK; } portPtr = &port->mNext; } -} - -// GetStaticQDFlushManager() -// -// Most calls through nsQDFlushManager are expected to be made through -// a global object, through the static sQDFlushPort method. Because -// constructors and destructors on static objects are distrusted, each -// call into sQDFlushPort obtains the static object by calling here. -// If the object does not yet exist, it is created. To handle destruction, -// a shutdown observer is added. The observer handles teardown of the -// static manager object and all attached port objects. -// -// protected static -nsQDFlushManager* -nsQDFlushManager::GetStaticQDFlushManager() -{ - if (!sQDFlushManager) - { - // The static flush manager has not yet been initialized. Create it. - sQDFlushManager = new nsQDFlushManager(); - NS_ASSERTION(sQDFlushManager, "failed to create flush manager"); - if (!sQDFlushManager) - { - // Early return, avoid creating a useless observer. - return nsnull; - } - - // Create a shutdown observer to handle destruction. - sQDFlushObserver = new nsQDFlushObserver(sQDFlushManager); - NS_ASSERTION(sQDFlushObserver, "failed to create observer"); - if (sQDFlushObserver) - { - // register for shutdown - nsresult rv; - nsCOMPtr observerService( - do_GetService("@mozilla.org/observer-service;1", &rv)); - if (NS_SUCCEEDED(rv)) - { - // There's not much we can or should do if this fails. - observerService->AddObserver(sQDFlushObserver, - NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE); - } - } - } - - return sQDFlushManager; + return NS_OK; } // nsQDFlushPort @@ -411,31 +295,3 @@ nsQDFlushPort::Notify(nsITimer* aTimer) return NS_OK; } - -// nsQDFlushObserver - -nsQDFlushObserver::nsQDFlushObserver(nsQDFlushManager* aParent) -: mParent(aParent) -{ -} - -nsQDFlushObserver::~nsQDFlushObserver() -{ -} - -// nsIObserver implementation - -NS_IMPL_ISUPPORTS1(nsQDFlushObserver, nsIObserver) - -// Observe(aSubject, aTopic, aData) -// -// Shutdown callback. Delete static object and any attached port objects. -NS_IMETHODIMP -nsQDFlushObserver::Observe(nsISupports* aSubject, const char* aTopic, - const PRUnichar* aData) -{ - NS_ASSERTION(!nsCRT::strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID,aTopic), - "Shutdown observer called with wrong topic\n"); - delete mParent; - return NS_OK; -} diff --git a/mozilla/gfx/src/mac/nsQDFlushManager.h b/mozilla/gfx/src/mac/nsQDFlushManager.h index bc173a72bbf..c9ea4336634 100644 --- a/mozilla/gfx/src/mac/nsQDFlushManager.h +++ b/mozilla/gfx/src/mac/nsQDFlushManager.h @@ -41,44 +41,69 @@ #include "nscore.h" #include "nsCOMPtr.h" +#include "nsIQDFlushManager.h" #include "nsITimer.h" -#include "nsIObserver.h" #include // The expected use is to replace these calls: // ::QDFlushPortBuffer(port, region) // with these: -// nsQDFlushManager::sFlushPortBuffer(port,region) +// nsCOMPtr qdFlushManager = +// do_GetService("@mozilla.org/gfx/qdflushmanager;1"); +// qdFlushManager->FlushPortBuffer(port, region); +// and at port destruction time: +// qdFlushManager->RemovePort(port) -// These subservient classes are defined in nsQDFlushManager.cpp. -class nsQDFlushPort; -class nsQDFlushObserver; - -class NS_EXPORT nsQDFlushManager +class nsQDFlushPort : public nsITimerCallback { - // nsQDFlushObserver is responsible for destruction of the static object. - friend class nsQDFlushObserver; + // nsQDFlushManager is responsible for maintaining the list of port objects. + friend class nsQDFlushManager; + + NS_DECL_ISUPPORTS + NS_DECL_NSITIMERCALLBACK + +protected: + nsQDFlushPort(CGrafPtr aPort); + ~nsQDFlushPort(); + + void Init(CGrafPtr aPort); + void Destroy(); + void FlushPortBuffer(RgnHandle aRegion); + PRInt64 TimeUntilFlush(AbsoluteTime aNow); + + // To use the display's refresh rate as the update Hz, see + // http://developer.apple.com/documentation/Performance/Conceptual/Drawing/Articles/FlushingContent.html . + // Here, use a hard-coded 30 Hz instead. + static const PRUint32 kRefreshRateHz = 30; // Maximum number of updates + // per second + + nsQDFlushPort* mNext; // Next object in list + CGrafPtr mPort; // Associated port + AbsoluteTime mLastFlushTime; // Last QDFlushPortBuffer call + nsCOMPtr mFlushTimer; // Timer for scheduled flush + PRPackedBool mFlushTimerRunning; // Is it? +}; + +class NS_EXPORT nsQDFlushManager : public nsIQDFlushManager +{ + NS_DECL_ISUPPORTS + NS_DECL_NSIQDFLUSHMANAGER public: nsQDFlushManager(); ~nsQDFlushManager(); - void FlushPortBuffer(CGrafPtr aPort, - RgnHandle aRegion); - static void sFlushPortBuffer(CGrafPtr aPort, - RgnHandle aRegion); - protected: nsQDFlushPort* CreateOrGetPort(CGrafPtr aPort); - void RemovePort(CGrafPtr aPort); - - static nsQDFlushManager* GetStaticQDFlushManager(); nsQDFlushPort* mPortList; // Head of list - - static nsQDFlushManager* sQDFlushManager; // Static object - static nsQDFlushObserver* sQDFlushObserver; // Cleanup for static object }; +// 6F91262A-CF9E-4DDD-AA01-7A1FCCF14281 +#define NS_QDFLUSHMANAGER_CLASSNAME "QuickDraw Buffer Flusher" +#define NS_QDFLUSHMANAGER_CID \ + {0x6F91262A, 0xCF9E, 0x4DDD, {0xAA, 0x01, 0x7A, 0x1F, 0xCC, 0xF1, 0x42, 0x81}} +#define NS_QDFLUSHMANAGER_CONTRACTID "@mozilla.org/gfx/qdflushmanager;1" + #endif /* nsQDFlushManager_h___ */ diff --git a/mozilla/gfx/src/mac/nsRenderingContextMac.cpp b/mozilla/gfx/src/mac/nsRenderingContextMac.cpp index 514a6209411..bd99c5e77ed 100644 --- a/mozilla/gfx/src/mac/nsRenderingContextMac.cpp +++ b/mozilla/gfx/src/mac/nsRenderingContextMac.cpp @@ -38,6 +38,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsIInterfaceRequestorUtils.h" +#include "nsIServiceManager.h" #include "nsRenderingContextMac.h" #include "nsDeviceContextMac.h" #include "nsFontMetricsMac.h" @@ -50,9 +51,12 @@ #include "nsVoidArray.h" #include "nsGfxCIID.h" #include "nsGfxUtils.h" -#include "nsQDFlushManager.h" #include "nsCOMPtr.h" +#ifdef MOZ_WIDGET_COCOA +#include "nsIQDFlushManager.h" +#endif + #include "plhash.h" #include @@ -1426,7 +1430,10 @@ nsRenderingContextMac::FlushRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord ::SetRectRgn(rgn, pinToShort(x), pinToShort(y), pinToShort(x + w), pinToShort(y + h)); - nsQDFlushManager::sFlushPortBuffer(mPort, rgn); + nsCOMPtr qdFlushManager = + do_GetService("@mozilla.org/gfx/qdflushmanager;1"); + if (qdFlushManager) + qdFlushManager->FlushPortBuffer(mPort, rgn); } #endif return NS_OK; diff --git a/mozilla/widget/src/cocoa/nsChildView.mm b/mozilla/widget/src/cocoa/nsChildView.mm index 7790c2494bf..fd0bc546c19 100644 --- a/mozilla/widget/src/cocoa/nsChildView.mm +++ b/mozilla/widget/src/cocoa/nsChildView.mm @@ -53,10 +53,12 @@ #include "nsIEventSink.h" #include "nsIScrollableView.h" #include "nsIInterfaceRequestor.h" +#include "nsIServiceManager.h" #include "nsCarbonHelpers.h" #include "nsGfxUtils.h" #include "nsMacResources.h" +#include "nsIQDFlushManager.h" #import "nsCursorManager.h" #import "nsWindowMap.h" @@ -465,6 +467,15 @@ void nsChildView::TearDownView() [(NSView*)responder isDescendantOf:mView]) [win makeFirstResponder: [mView superview]]; + GrafPtr curPort = GetChildViewQuickDrawPort(); + if (curPort) + { + nsCOMPtr qdFlushManager = + do_GetService("@mozilla.org/gfx/qdflushmanager;1"); + if (qdFlushManager) + qdFlushManager->RemovePort(curPort); + } + [mView removeFromSuperviewWithoutNeedingDisplay]; [mView release]; mView = nil;