Bug 595156 - Always use BasicLayerManager when drawing in the titlebar. r=roc a=blocking2.0:betaN
authorMarkus Stange <mstange@themasta.com>
Fri, 15 Oct 2010 12:34:29 +0200
changeset 55858 94a24110bbf0df0c2709e7b19fa0657b041881b4
parent 55857 55d9426f9a573e0aebe5fa9bd54b7eab44828ebc
child 55859 1e685d9c9e704d698b80446d1f48df3313864a69
push id16311
push usermstange@themasta.com
push dateFri, 15 Oct 2010 10:39:22 +0000
treeherdermozilla-central@1e685d9c9e70 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, blocking2.0
bugs595156
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 595156 - Always use BasicLayerManager when drawing in the titlebar. r=roc a=blocking2.0:betaN
layout/base/nsDisplayList.cpp
toolkit/content/LightweightThemeConsumer.jsm
widget/public/nsIWidget.h
widget/src/android/nsWindow.cpp
widget/src/android/nsWindow.h
widget/src/cocoa/nsChildView.h
widget/src/cocoa/nsChildView.mm
widget/src/cocoa/nsCocoaWindow.h
widget/src/cocoa/nsCocoaWindow.mm
widget/src/windows/nsWindow.cpp
widget/src/windows/nsWindow.h
widget/src/xpwidgets/PuppetWidget.cpp
widget/src/xpwidgets/PuppetWidget.h
widget/src/xpwidgets/nsBaseWidget.cpp
widget/src/xpwidgets/nsBaseWidget.h
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -374,18 +374,19 @@ void nsDisplayList::PaintForFrame(nsDisp
 
   nsRefPtr<LayerManager> layerManager;
   if (aFlags & PAINT_USE_WIDGET_LAYERS) {
     nsIFrame* referenceFrame = aBuilder->ReferenceFrame();
     NS_ASSERTION(referenceFrame == nsLayoutUtils::GetDisplayRootFrame(referenceFrame),
                  "Reference frame must be a display root for us to use the layer manager");
     nsIWidget* window = referenceFrame->GetNearestWidget();
     if (window) {
-      layerManager = window->GetLayerManager();
-      if (layerManager) {
+      bool allowRetaining = true;
+      layerManager = window->GetLayerManager(&allowRetaining);
+      if (layerManager && allowRetaining) {
         aBuilder->LayerBuilder()->WillBeginRetainedLayerTransaction(layerManager);
       }
     }
   }
   if (!layerManager) {
     if (!aCtx) {
       NS_WARNING("Nowhere to paint into");
       return;
--- a/toolkit/content/LightweightThemeConsumer.jsm
+++ b/toolkit/content/LightweightThemeConsumer.jsm
@@ -93,25 +93,16 @@ LightweightThemeConsumer.prototype = {
       _setImage(footer, active, aData.footerURL);
       if (active && aData.footerURL)
         footer.setAttribute("lwthemefooter", "true");
       else
         footer.removeAttribute("lwthemefooter");
     }
 
 #ifdef XP_MACOSX
-
-    if (active && aData.accentcolor) {
-      root.setAttribute("activetitlebarcolor", aData.accentcolor);
-      root.setAttribute("inactivetitlebarcolor", aData.accentcolor);
-    } else {
-      root.removeAttribute("activetitlebarcolor");
-      root.removeAttribute("inactivetitlebarcolor");
-    }
-
     if (active)
       root.setAttribute("drawintitlebar", "true");
     else
       root.removeAttribute("drawintitlebar");
 #endif
   }
 }
 
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -112,20 +112,20 @@ typedef nsEventStatus (* EVENT_CALLBACK)
 #define NS_NATIVE_PLUGIN_PORT_CG    101
 #endif
 #ifdef XP_WIN
 #define NS_NATIVE_TSF_THREAD_MGR       100
 #define NS_NATIVE_TSF_CATEGORY_MGR     101
 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
 #endif
 
-// 8bd36c8c-8218-4859-bfbc-ca5d78b52f7d
+// cc443f0b-af39-415d-9c4b-7e06eaa8b13b
 #define NS_IWIDGET_IID \
-  { 0x8bd36c8c, 0x8218, 0x4859, \
-    { 0xbf, 0xbc, 0xca, 0x5d, 0x78, 0xb5, 0x2f, 0x7d } }
+  { 0xcc443f0b, 0xaf39, 0x415d, \
+    { 0x9c, 0x4b, 0x7e, 0x06, 0xea, 0xa8, 0xb1, 0x3b } }
 
 /*
  * Window shadow styles
  * Also used for the -moz-window-shadow CSS property
  */
 
 #define NS_STYLE_WINDOW_SHADOW_NONE             0
 #define NS_STYLE_WINDOW_SHADOW_DEFAULT          1
@@ -850,20 +850,21 @@ class nsIWidget : public nsISupports {
      * @return the toolkit this widget was created in. See nsToolkit.
      */
 
     virtual nsIToolkit* GetToolkit() = 0;    
 
     /**
      * Return the widget's LayerManager. The layer tree for that
      * LayerManager is what gets rendered to the widget.
-     * The layer manager is guaranteed to be the same for the lifetime
-     * of the widget.
+     *
+     * @param aAllowRetaining an outparam that states whether the returned
+     * layer manager should be used for retained layers
      */
-    virtual LayerManager* GetLayerManager() = 0;
+    virtual LayerManager* GetLayerManager(bool* aAllowRetaining = nsnull) = 0;
 
     /** 
      * Internal methods
      */
 
     //@{
     virtual void AddChild(nsIWidget* aChild) = 0;
     virtual void RemoveChild(nsIWidget* aChild) = 0;
--- a/widget/src/android/nsWindow.cpp
+++ b/widget/src/android/nsWindow.cpp
@@ -587,18 +587,21 @@ nsWindow::DispatchEvent(nsGUIEvent *aEve
 
 NS_IMETHODIMP
 nsWindow::SetWindowClass(const nsAString& xulWinType)
 {
     return NS_OK;
 }
 
 mozilla::layers::LayerManager*
-nsWindow::GetLayerManager()
+nsWindow::GetLayerManager(bool* aAllowRetaining)
 {
+    if (aAllowRetaining) {
+        *aAllowRetaining = true;
+    }
     if (mLayerManager) {
         return mLayerManager;
     }
 
     printf_stderr("nsWindow::GetLayerManager\n");
 
     nsWindow *topWindow = TopWindow();
 
--- a/widget/src/android/nsWindow.h
+++ b/widget/src/android/nsWindow.h
@@ -157,17 +157,17 @@ public:
     NS_IMETHOD GetIMEEnabled(PRUint32* aState);
     NS_IMETHOD CancelIMEComposition();
 
     NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
     NS_IMETHOD OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd);
     NS_IMETHOD OnIMESelectionChange(void);
     virtual nsIMEUpdatePreference GetIMEUpdatePreference();
 
-    LayerManager* GetLayerManager();
+    LayerManager* GetLayerManager(bool* aAllowRetaining = nsnull);
     gfxASurface* GetThebesSurface();
 
     NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent);
 protected:
     void BringToFront();
     nsWindow *FindTopLevel();
     PRBool DrawTo(gfxASurface *targetSurface);
     PRBool IsTopLevel();
--- a/widget/src/cocoa/nsChildView.h
+++ b/widget/src/cocoa/nsChildView.h
@@ -206,35 +206,33 @@ extern "C" long TSMProcessRawKeyEvent(Ev
 
 // Stop NSView hierarchy being changed during [ChildView drawRect:]
 - (void)delayedTearDown;
 
 - (void)sendFocusEvent:(PRUint32)eventType;
 
 - (void)handleMouseMoved:(NSEvent*)aEvent;
 
-- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext;
+- (void)drawRect:(NSRect)aRect inTitlebarContext:(CGContextRef)aContext;
 
 - (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent
                             enter:(BOOL)aEnter
                              type:(nsMouseEvent::exitType)aType;
 
 #ifndef NP_NO_CARBON
 - (void) processPluginKeyEvent:(EventRef)aKeyEvent;
 #endif
 - (void)pluginRequestsComplexTextInputForCurrentEvent;
 
 - (void)update;
 - (void)lockFocus;
 - (void) _surfaceNeedsUpdate:(NSNotification*)notification;
 
 - (BOOL)isPluginView;
 
-- (BOOL)isUsingOpenGL;
-
 // Simple gestures support
 //
 // XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
 // rotateWithEvent, and endGestureWithEvent methods are part of a
 // PRIVATE interface exported by nsResponder and reverse-engineering
 // was necessary to obtain the methods' prototypes. Thus, Apple may
 // change the interface in the future without notice.
 //
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -187,16 +187,18 @@ PRUint32 nsChildView::sLastInputEventCou
 
 - (void)maybeInitContextMenuTracking;
 
 + (NSEvent*)makeNewCocoaEventWithType:(NSEventType)type fromEvent:(NSEvent*)theEvent;
 
 - (float)beginMaybeResetUnifiedToolbar;
 - (void)endMaybeResetUnifiedToolbar:(float)aOldHeight;
 
+- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext;
+
 #if USE_CLICK_HOLD_CONTEXTMENU
  // called on a timer two seconds after a mouse down to see if we should display
  // a context menu (click-hold)
 - (void)clickHoldCallback:(id)inEvent;
 #endif
 
 #ifdef ACCESSIBILITY
 - (id<mozAccessible>)accessible;
@@ -2593,21 +2595,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
   }
 }
 
 - (void) _surfaceNeedsUpdate:(NSNotification*)notification
 {
    [self update];
 }
 
-- (BOOL) isUsingOpenGL
-{
-    return mGeckoChild && mGeckoChild->GetLayerManager()->GetBackendType() == LayerManager::LAYERS_OPENGL;
-}
-
 // The display system has told us that a portion of our view is dirty. Tell
 // gecko to paint it
 - (void)drawRect:(NSRect)aRect
 {
   float oldHeight = [self beginMaybeResetUnifiedToolbar];
 
   CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
   [self drawRect:aRect inContext:cgContext];
@@ -2616,16 +2613,24 @@ NSEvent* gLastDragMouseDownEvent = nil;
   // to make sure the shadow is updated to the new contents.
   if ([[self window] isKindOfClass:[BaseWindow class]]) {
     [(BaseWindow*)[self window] deferredInvalidateShadow];
   }
 
   [self endMaybeResetUnifiedToolbar:oldHeight];
 }
 
+- (void)drawRect:(NSRect)aRect inTitlebarContext:(CGContextRef)aContext
+{
+  // Title bar drawing only works if we really draw into aContext, which only
+  // the basic layer manager will do.
+  nsBaseWidget::AutoUseBasicLayerManager setupLayerManager(mGeckoChild);
+  [self drawRect:aRect inContext:aContext];
+}
+
 - (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext
 {
   PRBool isVisible;
   if (!mGeckoChild || NS_FAILED(mGeckoChild->IsVisible(isVisible)) ||
       !isVisible)
     return;
 
 #ifndef NP_NO_QUICKDRAW
--- a/widget/src/cocoa/nsCocoaWindow.h
+++ b/widget/src/cocoa/nsCocoaWindow.h
@@ -249,17 +249,17 @@ public:
     NS_IMETHOD              SetCursor(nsCursor aCursor);
     NS_IMETHOD              SetCursor(imgIContainer* aCursor, PRUint32 aHotspotX, PRUint32 aHotspotY);
 
     NS_IMETHOD              SetTitle(const nsAString& aTitle);
 
     NS_IMETHOD Invalidate(const nsIntRect &aRect, PRBool aIsSynchronous);
     NS_IMETHOD Update();
     virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
-    virtual LayerManager* GetLayerManager();
+    virtual LayerManager* GetLayerManager(bool* aAllowRetaining = nsnull);
     NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus) ;
     NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, nsIMenuRollup * aMenuRollup,
                                    PRBool aDoCapture, PRBool aConsumeRollupEvent);
     NS_IMETHOD GetAttention(PRInt32 aCycleCount);
     virtual PRBool HasPendingInputEvent();
     virtual nsTransparencyMode GetTransparencyMode();
     virtual void SetTransparencyMode(nsTransparencyMode aMode);
     NS_IMETHOD SetWindowShadowStyle(PRInt32 aStyle);
--- a/widget/src/cocoa/nsCocoaWindow.mm
+++ b/widget/src/cocoa/nsCocoaWindow.mm
@@ -927,20 +927,20 @@ nsCocoaWindow::ConfigureChildren(const n
 {
   if (mPopupContentView) {
     mPopupContentView->ConfigureChildren(aConfigurations);
   }
   return NS_OK;
 }
 
 LayerManager*
-nsCocoaWindow::GetLayerManager()
+nsCocoaWindow::GetLayerManager(bool* aAllowRetaining)
 {
   if (mPopupContentView) {
-    return mPopupContentView->GetLayerManager();
+    return mPopupContentView->GetLayerManager(aAllowRetaining);
   }
   return nsnull;
 }
 
 nsTransparencyMode nsCocoaWindow::GetTransparencyMode()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
@@ -2430,41 +2430,34 @@ ContentPatternDrawCallback(void* aInfo, 
   // Gecko drawing assumes flippedness, but the current context isn't flipped
   // (because we're painting into the window's border view, which is not a
   // ChildView, so it isn't flpped).
   // So we need to set a flip transform.
   CGContextScaleCTM(aContext, 1.0f, -1.0f);
   CGContextTranslateCTM(aContext, 0.0f, -[window frame].size.height);
 
   NSRect titlebarRect = NSMakeRect(0, 0, [window frame].size.width, [window titlebarHeight]);
-  [(ChildView*)view drawRect:titlebarRect inContext:aContext];
+  [(ChildView*)view drawRect:titlebarRect inTitlebarContext:aContext];
 }
 
 - (void)setFill
 {
-  CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-  CGPatternDrawPatternCallback cb;
-  float patternWidth;
-  NSView* view = [[[mWindow contentView] subviews] lastObject];
-  if (view && [view isKindOfClass:[ChildView class]] && [(ChildView*)view isUsingOpenGL]) {
-    cb = &RepeatedPatternDrawCallback;
-    patternWidth = sPatternWidth;
-  } else {
-    cb = [mWindow drawsContentsIntoWindowFrame] ?
+  CGPatternDrawPatternCallback cb = [mWindow drawsContentsIntoWindowFrame] ?
                                       &ContentPatternDrawCallback : &RepeatedPatternDrawCallback;
-    patternWidth = [mWindow drawsContentsIntoWindowFrame] ? [mWindow frame].size.width : sPatternWidth;
-  }
+  float patternWidth = [mWindow drawsContentsIntoWindowFrame] ? [mWindow frame].size.width : sPatternWidth;
+
   CGPatternCallbacks callbacks = {0, cb, NULL};
   CGPatternRef pattern = CGPatternCreate(mWindow, CGRectMake(0.0f, 0.0f, patternWidth, [mWindow frame].size.height), 
                                          CGAffineTransformIdentity, patternWidth, [mWindow frame].size.height,
                                          kCGPatternTilingConstantSpacing, true, &callbacks);
 
   // Set the pattern as the fill, which is what we were asked to do. All our
   // drawing will take place in the patternDraw callback.
   CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
+  CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
   CGContextSetFillColorSpace(context, patternSpace);
   CGColorSpaceRelease(patternSpace);
   CGFloat component = 1.0f;
   CGContextSetFillPattern(context, pattern, &component);
   CGPatternRelease(pattern);
 }
 
 - (void)set
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -3175,18 +3175,22 @@ nsWindow::HasPendingInputEvent()
  *
  * SECTION: nsIWidget::GetLayerManager
  *
  * Get the layer manager associated with this widget.
  *
  **************************************************************/
 
 mozilla::layers::LayerManager*
-nsWindow::GetLayerManager()
-{
+nsWindow::GetLayerManager(bool* aAllowRetaining)
+{
+  if (aAllowRetaining) {
+    *aAllowRetaining = true;
+  }
+
 #ifndef WINCE
   if (!mLayerManager) {
     nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
 
     PRBool accelerateByDefault = PR_TRUE;
     PRBool disableAcceleration = PR_FALSE;
     PRBool preferOpenGL = PR_FALSE;
     PRBool useD3D10 = PR_FALSE;
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -161,17 +161,17 @@ public:
   virtual nsIntSize       ClientToWindowSize(const nsIntSize& aClientSize);
   NS_IMETHOD              DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus);
   NS_IMETHOD              EnableDragDrop(PRBool aEnable);
   NS_IMETHOD              CaptureMouse(PRBool aCapture);
   NS_IMETHOD              CaptureRollupEvents(nsIRollupListener * aListener, nsIMenuRollup * aMenuRollup,
                                               PRBool aDoCapture, PRBool aConsumeRollupEvent);
   NS_IMETHOD              GetAttention(PRInt32 aCycleCount);
   virtual PRBool          HasPendingInputEvent();
-  virtual LayerManager*   GetLayerManager();
+  virtual LayerManager*   GetLayerManager(bool* aAllowRetaining = nsnull);
   gfxASurface             *GetThebesSurface();
   NS_IMETHOD              OnDefaultButtonLoaded(const nsIntRect &aButtonRect);
   NS_IMETHOD              OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta, PRBool aIsHorizontal, PRInt32 &aOverriddenDelta);
 
   virtual nsresult        SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
                                                    PRInt32 aNativeKeyCode,
                                                    PRUint32 aModifierFlags,
                                                    const nsAString& aCharacters,
--- a/widget/src/xpwidgets/PuppetWidget.cpp
+++ b/widget/src/xpwidgets/PuppetWidget.cpp
@@ -305,21 +305,24 @@ PuppetWidget::DispatchEvent(nsGUIEvent* 
     event->widget = mChild;
     mChild->DispatchEvent(event, aStatus);
   }
 
   return NS_OK;
 }
 
 LayerManager*
-PuppetWidget::GetLayerManager()
+PuppetWidget::GetLayerManager(bool* aAllowRetaining)
 {
   if (!mLayerManager) {
     mLayerManager = new BasicShadowLayerManager(this);
   }
+  if (aAllowRetaining) {
+    *aAllowRetaining = true;
+  }
   return mLayerManager;
 }
 
 gfxASurface*
 PuppetWidget::GetThebesSurface()
 {
   return mSurface;
 }
--- a/widget/src/xpwidgets/PuppetWidget.h
+++ b/widget/src/xpwidgets/PuppetWidget.h
@@ -159,17 +159,17 @@ public:
                                  PRBool aDoCapture, PRBool aConsumeRollupEvent)
   { return NS_ERROR_UNEXPECTED; }
 
   //
   // nsBaseWidget methods we override
   //
 
 //NS_IMETHOD              CaptureMouse(PRBool aCapture);
-  virtual LayerManager*     GetLayerManager();
+  virtual LayerManager*     GetLayerManager(bool* aAllowRetaining = nsnull);
 //  virtual nsIDeviceContext* GetDeviceContext();
   virtual gfxASurface*      GetThebesSurface();
 
   NS_IMETHOD ResetInputState();
   NS_IMETHOD SetIMEOpenState(PRBool aState);
   NS_IMETHOD GetIMEOpenState(PRBool *aState);
   NS_IMETHOD SetIMEEnabled(PRUint32 aState);
   NS_IMETHOD GetIMEEnabled(PRUint32 *aState);
--- a/widget/src/xpwidgets/nsBaseWidget.cpp
+++ b/widget/src/xpwidgets/nsBaseWidget.cpp
@@ -101,16 +101,17 @@ nsBaseWidget::nsBaseWidget()
 , mViewCallback(nsnull)
 , mContext(nsnull)
 , mToolkit(nsnull)
 , mCursor(eCursor_standard)
 , mWindowType(eWindowType_child)
 , mBorderStyle(eBorderStyle_none)
 , mOnDestroyCalled(PR_FALSE)
 , mUseAcceleratedRendering(PR_FALSE)
+, mTemporarilyUseBasicLayerManager(PR_FALSE)
 , mBounds(0,0,0,0)
 , mOriginalBounds(nsnull)
 , mClipRectCount(0)
 , mZIndex(0)
 , mSizeMode(nsSizeMode_Normal)
 , mPopupLevel(ePopupLevelTop)
 {
 #ifdef NOISY_WIDGET_LEAKS
@@ -756,16 +757,27 @@ nsBaseWidget::AutoLayerManagerSetup::~Au
     static_cast<BasicLayerManager*>(mWidget->GetLayerManager());
   if (manager) {
     NS_ASSERTION(manager->GetBackendType() == LayerManager::LAYERS_BASIC,
       "AutoLayerManagerSetup instantiated for non-basic layer backend!");
     manager->SetDefaultTarget(nsnull, BasicLayerManager::BUFFER_NONE);
   }
 }
 
+nsBaseWidget::AutoUseBasicLayerManager::AutoUseBasicLayerManager(nsBaseWidget* aWidget)
+  : mWidget(aWidget)
+{
+  mWidget->mTemporarilyUseBasicLayerManager = PR_TRUE;
+}
+
+nsBaseWidget::AutoUseBasicLayerManager::~AutoUseBasicLayerManager()
+{
+  mWidget->mTemporarilyUseBasicLayerManager = PR_FALSE;
+}
+
 PRBool
 nsBaseWidget::GetShouldAccelerate()
 {
   nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
 
   PRBool disableAcceleration = PR_FALSE;
   PRBool accelerateByDefault = PR_TRUE;
 
@@ -789,17 +801,17 @@ nsBaseWidget::GetShouldAccelerate()
     return PR_FALSE;
 
   if (accelerateByDefault)
     return PR_TRUE;
 
   return mUseAcceleratedRendering;
 }
 
-LayerManager* nsBaseWidget::GetLayerManager()
+LayerManager* nsBaseWidget::GetLayerManager(bool* aAllowRetaining)
 {
   if (!mLayerManager) {
     nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
 
     mUseAcceleratedRendering = GetShouldAccelerate();
 
     if (mUseAcceleratedRendering) {
       nsRefPtr<LayerManagerOGL> layerManager =
@@ -811,20 +823,28 @@ LayerManager* nsBaseWidget::GetLayerMana
        * platforms on LayerManagerOGL should ensure their widget is able to
        * deal with it though!
        */
       if (layerManager->Initialize()) {
         mLayerManager = layerManager;
       }
     }
     if (!mLayerManager) {
-      mLayerManager = CreateBasicLayerManager();
+      mBasicLayerManager = mLayerManager = CreateBasicLayerManager();
     }
   }
-  return mLayerManager;
+  if (mTemporarilyUseBasicLayerManager && !mBasicLayerManager) {
+    mBasicLayerManager = CreateBasicLayerManager();
+  }
+  LayerManager* usedLayerManager = mTemporarilyUseBasicLayerManager ?
+                                     mBasicLayerManager : mLayerManager;
+  if (aAllowRetaining) {
+    *aAllowRetaining = (usedLayerManager == mLayerManager);
+  }
+  return usedLayerManager;
 }
 
 BasicLayerManager* nsBaseWidget::CreateBasicLayerManager()
 {
 #if !defined(MOZ_IPC)
       return new BasicLayerManager(this);
 #else
       return new BasicShadowLayerManager(this);
--- a/widget/src/xpwidgets/nsBaseWidget.h
+++ b/widget/src/xpwidgets/nsBaseWidget.h
@@ -110,17 +110,17 @@ public:
   virtual nsTransparencyMode GetTransparencyMode();
   virtual void            GetWindowClipRegion(nsTArray<nsIntRect>* aRects);
   NS_IMETHOD              SetWindowShadowStyle(PRInt32 aStyle);
   virtual void            SetShowsToolbarButton(PRBool aShow) {}
   NS_IMETHOD              HideWindowChrome(PRBool aShouldHide);
   NS_IMETHOD              MakeFullScreen(PRBool aFullScreen);
   virtual nsIDeviceContext* GetDeviceContext();
   virtual nsIToolkit*     GetToolkit();
-  virtual LayerManager*   GetLayerManager();
+  virtual LayerManager*   GetLayerManager(bool* aAllowRetaining = nsnull);
   virtual gfxASurface*    GetThebesSurface();
   NS_IMETHOD              SetModal(PRBool aModal); 
   NS_IMETHOD              SetWindowClass(const nsAString& xulWinType);
   NS_IMETHOD              SetBounds(const nsIntRect &aRect);
   NS_IMETHOD              GetBounds(nsIntRect &aRect);
   NS_IMETHOD              GetClientBounds(nsIntRect &aRect);
   NS_IMETHOD              GetScreenBounds(nsIntRect &aRect);
   virtual nsIntPoint      GetClientOffset();
@@ -197,16 +197,25 @@ public:
     AutoLayerManagerSetup(nsBaseWidget* aWidget, gfxContext* aTarget,
                           BasicLayerManager::BufferMode aDoubleBuffering);
     ~AutoLayerManagerSetup();
   private:
     nsBaseWidget* mWidget;
   };
   friend class AutoLayerManagerSetup;
 
+  class AutoUseBasicLayerManager {
+  public:
+    AutoUseBasicLayerManager(nsBaseWidget* aWidget);
+    ~AutoUseBasicLayerManager();
+  private:
+    nsBaseWidget* mWidget;
+  };
+  friend class AutoUseBasicLayerManager;
+
 protected:
 
   virtual void            ResolveIconName(const nsAString &aIconName,
                                           const nsAString &aIconSuffix,
                                           nsILocalFile **aResult);
   virtual void            OnDestroy();
   virtual void            BaseCreate(nsIWidget *aParent,
                                      const nsIntRect &aRect,
@@ -250,23 +259,25 @@ protected:
 protected: 
   void*             mClientData;
   ViewWrapper*      mViewWrapperPtr;
   EVENT_CALLBACK    mEventCallback;
   EVENT_CALLBACK    mViewCallback;
   nsIDeviceContext* mContext;
   nsIToolkit*       mToolkit;
   nsRefPtr<LayerManager> mLayerManager;
+  nsRefPtr<LayerManager> mBasicLayerManager;
   nscolor           mBackground;
   nscolor           mForeground;
   nsCursor          mCursor;
   nsWindowType      mWindowType;
   nsBorderStyle     mBorderStyle;
   PRPackedBool      mOnDestroyCalled;
   PRPackedBool      mUseAcceleratedRendering;
+  PRPackedBool      mTemporarilyUseBasicLayerManager;
   nsIntRect         mBounds;
   nsIntRect*        mOriginalBounds;
   // When this pointer is null, the widget is not clipped
   nsAutoArrayPtr<nsIntRect> mClipRects;
   PRUint32          mClipRectCount;
   PRInt32           mZIndex;
   nsSizeMode        mSizeMode;
   nsPopupLevel      mPopupLevel;