Bug 621762 - Change the way native windows are notified about toolbars. r=roc, a=betaN
authorMarkus Stange <mstange@themasta.com>
Tue, 11 Jan 2011 14:03:16 +0100
changeset 60289 6cfffe34531c366309ad5842b68fd374d22950e4
parent 60288 57eb3d4405930d4905e47b45a458e4a958075f66
child 60290 d414fbea7ba3c74b48f7575897fb790fc8c909c5
push id17914
push usermstange@themasta.com
push dateTue, 11 Jan 2011 13:04:53 +0000
treeherdermozilla-central@6cfffe34531c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, betaN
bugs621762
milestone2.0b10pre
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 621762 - Change the way native windows are notified about toolbars. r=roc, a=betaN
gfx/src/nsITheme.h
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
widget/public/nsIWidget.h
widget/src/cocoa/nsChildView.h
widget/src/cocoa/nsChildView.mm
widget/src/cocoa/nsCocoaWindow.h
widget/src/cocoa/nsCocoaWindow.mm
widget/src/cocoa/nsNativeThemeCocoa.h
widget/src/cocoa/nsNativeThemeCocoa.mm
widget/src/xpwidgets/nsBaseWidget.h
--- a/gfx/src/nsITheme.h
+++ b/gfx/src/nsITheme.h
@@ -97,34 +97,17 @@ public:
    */
   NS_IMETHOD DrawWidgetBackground(nsIRenderingContext* aContext,
                                   nsIFrame* aFrame,
                                   PRUint8 aWidgetType,
                                   const nsRect& aRect,
                                   const nsRect& aDirtyRect) = 0;
 
   /**
-   * Notifies the theme engine that a particular themed widget exists
-   * at the given rectangle within the window aWindow.
-   * For certain appearance values (currently only
-   * NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR and NS_THEME_TOOLBAR) this gets
-   * called during every paint to a window, for every themed widget of
-   * the right type within the
-   * window, except for themed widgets which are transformed or have
-   * effects applied to them (e.g. CSS opacity or filters).
-   * Note that a DrawWidgetBackground for the widget might not be called
-   * during the paint, since ThebesLayers can cache rendered content.
-   * This could sometimes be called during display list construction
-   * outside of painting.
-   * If called during painting, it will be called before we actually
-   * paint anything.
-   * 
-   * @param aWidgetType the -moz-appearance value for the themed widget
-   * @param aRect the device-pixel rect within aWindow for the themed
-   * widget
+   * XXX Unused. This is only here because the interface is frozen for 2.0.
    */
   virtual void RegisterWidgetGeometry(nsIWidget* aWindow,
                                       PRUint8 aWidgetType,
                                       const nsIntRect& aRect) {}
 
   /**
    * Get the computed CSS border for the widget, in pixels.
    */
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -256,16 +256,27 @@ void
 nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
                                      const nsRect& aDirtyRect) {
   if (CurrentPresShellState()->mPresShell != aReferenceFrame->PresContext()->PresShell()) {
     // Must have not allocated a state for this presshell, presumably due
     // to OOM.
     return;
   }
 
+  // If we're finished building display list items for painting of the outermost
+  // pres shell, notify the widget about any toolbars we've encountered.
+  if (mIsPaintingToWindow && mPresShellStates.Length() == 1) {
+    nsIWidget* widget = aReferenceFrame->GetNearestWidget();
+    if (widget) {
+      nsIWidget_MOZILLA_2_0_BRANCH* widget2 =
+        static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget);
+      widget2->UpdateThemeGeometries(CurrentPresShellState()->mThemeGeometries);
+    }
+  }
+
   // Unmark and pop off the frames marked for display in this pres shell.
   PRUint32 firstFrameForShell = CurrentPresShellState()->mFirstFrameMarkedForDisplay;
   for (PRUint32 i = firstFrameForShell;
        i < mFramesMarkedForDisplay.Length(); ++i) {
     UnmarkFrameForDisplay(mFramesMarkedForDisplay[i]);
   }
   mFramesMarkedForDisplay.SetLength(firstFrameForShell);
   mPresShellStates.SetLength(mPresShellStates.Length() - 1);
@@ -710,59 +721,48 @@ PRBool nsDisplayItem::RecomputeVisibilit
 
 void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
                                 nsIRenderingContext* aCtx) {
   aCtx->SetColor(mColor);
   aCtx->FillRect(mVisibleRect);
 }
 
 static void
-RegisterThemeWidgetGeometry(nsIFrame* aFrame)
+RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
 {
-  nsPresContext* presContext = aFrame->PresContext();
-  nsITheme* theme = presContext->GetTheme();
-  if (!theme)
-    return;
-
   nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(aFrame);
-  nsIWidget* widget = displayRoot->GetNearestWidget();
-  // If the display root doesn't have a widget, just bail. Something
-  // weird is going on, maybe we're printing?
-  if (!widget)
-    return;
 
   for (nsIFrame* f = aFrame; f; f = f->GetParent()) {
     // Bail out if we're in a transformed subtree
     if (f->IsTransformed())
       return;
     // Bail out if we're not in the displayRoot's document
     if (!f->GetParent() && f != displayRoot)
       return;
   }
 
   nsRect borderBox(aFrame->GetOffsetTo(displayRoot), aFrame->GetSize());
-  theme->RegisterWidgetGeometry(widget,
-      aFrame->GetStyleDisplay()->mAppearance,
-      borderBox.ToNearestPixels(presContext->AppUnitsPerDevPixel()));
+  aBuilder->RegisterThemeGeometry(aFrame->GetStyleDisplay()->mAppearance,
+      borderBox.ToNearestPixels(aFrame->PresContext()->AppUnitsPerDevPixel()));
 }
 
 nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
                                          nsIFrame* aFrame)
   : nsDisplayItem(aBuilder, aFrame),
     mSnappingEnabled(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform())
 {
   MOZ_COUNT_CTOR(nsDisplayBackground);
   const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
   mIsThemed = mFrame->IsThemed(disp, &mThemeTransparency);
 
-  // Perform necessary RegisterWidgetGeometry
+  // Perform necessary RegisterThemeGeometry
   if (mIsThemed &&
       (disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
        disp->mAppearance == NS_THEME_TOOLBAR)) {
-    RegisterThemeWidgetGeometry(aFrame);
+    RegisterThemeGeometry(aBuilder, aFrame);
   }
 }
 
 // Helper for RoundedRectIntersectsRect.
 static PRBool
 CheckCorner(nscoord aXOffset, nscoord aYOffset,
             nscoord aXRadius, nscoord aYRadius)
 {
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -122,16 +122,17 @@ class nsDisplayItem;
  * coordinate system for all display list items. Some of the parameters are
  * available from the prescontext/presshell, but we copy them into the builder
  * for faster/more convenient access.
  */
 class nsDisplayListBuilder {
 public:
   typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
   typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
+  typedef nsIWidget::ThemeGeometry ThemeGeometry;
 
   /**
    * @param aReferenceFrame the frame at the root of the subtree; its origin
    * is the origin of the reference coordinate system for this display list
    * @param aIsForEvents PR_TRUE if we're creating this list in order to
    * determine which frame is under the mouse position
    * @param aBuildCaret whether or not we should include the caret in any
    * display lists that we make.
@@ -366,17 +367,39 @@ public:
    * the display list, even though it doesn't intersect the dirty
    * rect, because it may have out-of-flows that do so.
    */
   bool ShouldDescendIntoFrame(nsIFrame* aFrame) const {
     return
       (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
       GetIncludeAllOutOfFlows();
   }
-  
+
+  /**
+   * Notifies the builder that a particular themed widget exists
+   * at the given rectangle within the currently built display list.
+   * For certain appearance values (currently only
+   * NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR and NS_THEME_TOOLBAR) this gets
+   * called during every display list construction, for every themed widget of
+   * the right type within the display list, except for themed widgets which
+   * are transformed or have effects applied to them (e.g. CSS opacity or
+   * filters).
+   *
+   * @param aWidgetType the -moz-appearance value for the themed widget
+   * @param aRect the device-pixel rect relative to the widget's displayRoot
+   * for the themed widget
+   */
+  void RegisterThemeGeometry(PRUint8 aWidgetType,
+                             const nsIntRect& aRect) {
+    if (mIsPaintingToWindow) {
+      ThemeGeometry geometry(aWidgetType, aRect);
+      CurrentPresShellState()->mThemeGeometries.AppendElement(geometry);
+    }
+  }
+
   /**
    * Allocate memory in our arena. It will only be freed when this display list
    * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
    * destructors are called as soon as the item is no longer used.
    */
   void* Allocate(size_t aSize);
   
   /**
@@ -429,16 +452,17 @@ public:
   }
 
 private:
   struct PresShellState {
     nsIPresShell* mPresShell;
     nsIFrame*     mCaretFrame;
     PRUint32      mFirstFrameMarkedForDisplay;
     PRPackedBool  mIsBackgroundOnly;
+    nsAutoTArray<ThemeGeometry,2> mThemeGeometries;
   };
   PresShellState* CurrentPresShellState() {
     NS_ASSERTION(mPresShellStates.Length() > 0,
                  "Someone forgot to enter a presshell");
     return &mPresShellStates[mPresShellStates.Length() - 1];
   }
 
   FrameLayerBuilder              mLayerBuilder;
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -257,16 +257,29 @@ class nsIWidget : public nsISupports {
 #ifdef MOZ_IPC
   protected:
     typedef mozilla::dom::PBrowserChild PBrowserChild;
 #endif
 
   public:
     typedef mozilla::layers::LayerManager LayerManager;
 
+    // Used in UpdateThemeGeometries.
+    struct ThemeGeometry {
+      // The -moz-appearance value for the themed widget
+      PRUint8 mWidgetType;
+      // The device-pixel rect within the window for the themed widget
+      nsIntRect mRect;
+
+      ThemeGeometry(PRUint8 aWidgetType, const nsIntRect& aRect)
+       : mWidgetType(aWidgetType)
+       , mRect(aRect)
+      { }
+    };
+
     NS_DECLARE_STATIC_IID_ACCESSOR(NS_IWIDGET_IID)
 
     nsIWidget()
       : mLastChild(nsnull)
       , mPrevSibling(nsnull)
     {}
 
         
@@ -1402,13 +1415,27 @@ class nsIWidget_MOZILLA_2_0_BRANCH : pub
 
     /**
      * Called after the LayerManager draws the layer tree
      *
      * @param aManager The drawing LayerManager.
      * @param aRect Current widget rect that is being drawn.
      */
     virtual void DrawOver(LayerManager* aManager, nsIntRect aRect) = 0;
+
+    /**
+     * Called when Gecko knows which themed widgets exist in this window.
+     * The passed array contains an entry for every themed widget of the right
+     * type (currently only NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR and
+     * NS_THEME_TOOLBAR) within the window, except for themed widgets which are
+     * transformed or have effects applied to them (e.g. CSS opacity or
+     * filters).
+     * This could sometimes be called during display list construction
+     * outside of painting.
+     * If called during painting, it will be called before we actually
+     * paint anything.
+     */
+    virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIWidget_MOZILLA_2_0_BRANCH, NS_IWIDGET_MOZILLA_2_0_BRANCH_IID)
 
 #endif // nsIWidget_h__
--- a/widget/src/cocoa/nsChildView.h
+++ b/widget/src/cocoa/nsChildView.h
@@ -390,16 +390,18 @@ public:
   
 #ifdef ACCESSIBILITY
   already_AddRefed<nsAccessible> GetDocumentAccessible();
 #endif
 
   virtual gfxASurface* GetThebesSurface();
   virtual void DrawOver(LayerManager* aManager, nsIntRect aRect);
 
+  virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries);
+
   NS_IMETHOD BeginSecureKeyboardInput();
   NS_IMETHOD EndSecureKeyboardInput();
 
   void              HidePlugin();
   void              UpdatePluginPort();
 
   void              ResetParent();
 
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -66,16 +66,17 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsIServiceManager.h"
 #include "nsILocalFile.h"
 #include "nsILocalFileMac.h"
 #include "nsGfxCIID.h"
 #include "nsIMenuRollup.h"
 #include "nsIDOMSimpleGestureEvent.h"
 #include "nsIPluginInstance.h"
+#include "nsThemeConstants.h"
 
 #include "nsDragService.h"
 #include "nsClipboard.h"
 #include "nsCursorManager.h"
 #include "nsWindowMap.h"
 #include "nsCocoaUtils.h"
 #include "nsMenuUtilsX.h"
 #include "nsMenuBarX.h"
@@ -184,19 +185,16 @@ PRUint32 nsChildView::sLastInputEventCou
 - (BOOL)isRectObscuredBySubview:(NSRect)inRect;
 
 - (void)processPendingRedraws;
 
 - (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
 
@@ -2081,16 +2079,37 @@ void
 nsChildView::DrawOver(LayerManager* aManager, nsIntRect aRect)
 {
   nsCocoaWindow *cocoaWindow = GetXULWindowWidget();
   if (cocoaWindow) {
     cocoaWindow->DrawOver(aManager, aRect);
   }
 }
 
+void
+nsChildView::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries)
+{
+  NSWindow* win = [mView window];
+  if (!win || ![win isKindOfClass:[ToolbarWindow class]])
+    return;
+
+  float unifiedToolbarHeight = 0;
+  nsIntRect topPixelStrip(0, 0, [win frame].size.width, 1);
+
+  for (PRUint32 i = 0; i < aThemeGeometries.Length(); ++i) {
+    const ThemeGeometry& g = aThemeGeometries[i];
+    if ((g.mWidgetType == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
+         g.mWidgetType == NS_THEME_TOOLBAR) &&
+        g.mRect.Contains(topPixelStrip)) {
+      unifiedToolbarHeight = g.mRect.YMost();
+    }
+  }
+  [(ToolbarWindow*)win setUnifiedToolbarHeight:unifiedToolbarHeight];
+}
+
 NS_IMETHODIMP
 nsChildView::BeginSecureKeyboardInput()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   nsresult rv = nsBaseWidget::BeginSecureKeyboardInput();
   if (NS_SUCCEEDED(rv))
     ::EnableSecureEventInput();
@@ -2593,65 +2612,40 @@ NSEvent* gLastDragMouseDownEvent = nil;
     }
 
     [mGLContext makeCurrentContext];
   }
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
-// Whenever we paint a toplevel window, we will be notified of any
-// unified toolbar in the window via
-// nsNativeThemeCocoa::RegisterWidgetGeometry. 
-- (float)beginMaybeResetUnifiedToolbar
-{
-  if (![[self window] isKindOfClass:[ToolbarWindow class]] ||
-      [self superview] != [[self window] contentView])
-    return 0.0;
-
-  return [(ToolbarWindow*)[self window] beginMaybeResetUnifiedToolbar];
-}
-
-- (void)endMaybeResetUnifiedToolbar:(float)aOldHeight
-{
-  if (![[self window] isKindOfClass:[ToolbarWindow class]] ||
-      [self superview] != [[self window] contentView])
-    return;
-
-  [(ToolbarWindow*)[self window] endMaybeResetUnifiedToolbar:aOldHeight];
-}
-
 -(void)update
 {
   if (mGLContext) {
     [mGLContext update];
   }
 }
 
 - (void) _surfaceNeedsUpdate:(NSNotification*)notification
 {
    [self update];
 }
 
 // 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];
 
   // If we're a transparent window and our contents have changed, we need
   // 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
 {
   if (!mGeckoChild)
     return;
 
   // Title bar drawing only works if we really draw into aContext, which only
--- a/widget/src/cocoa/nsCocoaWindow.h
+++ b/widget/src/cocoa/nsCocoaWindow.h
@@ -178,25 +178,22 @@ struct UnifiedGradientInfo {
 
 @end
 
 // NSWindow subclass for handling windows with toolbars.
 @interface ToolbarWindow : BaseWindow
 {
   TitlebarAndBackgroundColor *mColor;
   float mUnifiedToolbarHeight;
-  BOOL mInUnifiedToolbarReset;
   NSColor *mBackgroundColor;
 }
 // Pass nil here to get the default appearance.
 - (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
-- (void)notifyToolbarAt:(float)aY height:(float)aHeight;
+- (void)setUnifiedToolbarHeight:(float)aHeight;
 - (float)unifiedToolbarHeight;
-- (float)beginMaybeResetUnifiedToolbar;
-- (void)endMaybeResetUnifiedToolbar:(float)aOldHeight;
 - (float)titlebarHeight;
 - (NSRect)titlebarRect;
 - (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync;
 - (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect;
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
 @end
 
 class nsCocoaWindow : public nsBaseWidget, public nsPIWidgetCocoa
--- a/widget/src/cocoa/nsCocoaWindow.mm
+++ b/widget/src/cocoa/nsCocoaWindow.mm
@@ -2188,25 +2188,25 @@ static const NSString* kStateShowsToolba
 // 4) Whenever the window's main state changes and when [window display] is called,
 //    Cocoa redraws the titlebar using the patternDraw callback function.
 //
 // This class also provides us with a pill button to show/hide the toolbar.
 //
 // Drawing the unified gradient in the titlebar and the toolbar works like this:
 // 1) In the style sheet we set the toolbar's -moz-appearance to -moz-mac-unified-toolbar.
 // 2) When the toolbar is visible and we paint the application chrome
-//    window in nsChildView::drawRect, Gecko calls
-//    nsNativeThemeCocoa::RegisterWidgetGeometry for the widget type
+//    window, the array that Gecko passes nsChildView::UpdateThemeGeometries
+//    will contain an entry for the widget type NS_THEME_TOOLBAR or
 //    NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR.
-// 3) This finds the toolbar frame's ToolbarWindow and passes the toolbar
-//    frame's height to setUnifiedToolbarHeight.
-// 4) If the toolbar height has changed, a titlebar redraw is triggered by
-//    [self display] and the upper part of the unified gradient is drawn in the
-//    titlebar.
-// 5) DrawUnifiedToolbar draws the lower part of the unified gradient in the toolbar.
+// 3) nsChildView::UpdateThemeGeometries finds the toolbar frame's ToolbarWindow
+//    and passes the toolbar frame's height to setUnifiedToolbarHeight.
+// 4) If the toolbar height has changed, a titlebar redraw is triggered and the
+//    upper part of the unified gradient is drawn in the titlebar.
+// 5) The lower part of the unified gradient in the toolbar is drawn during
+//    normal window content painting in nsNativeThemeCocoa::DrawUnifiedToolbar.
 //
 // Whenever the unified gradient is drawn in the titlebar or the toolbar, both
 // titlebar height and toolbar height must be known in order to construct the
 // correct gradient (which is a linear gradient with the length
 // titlebarHeight + toolbarHeight - 1). But you can only get from the toolbar frame
 // to the containing window - the other direction doesn't work. That's why the
 // toolbar height is cached in the ToolbarWindow but nsNativeThemeCocoa can simply
 // query the window for its titlebar height when drawing the toolbar.
@@ -2219,17 +2219,16 @@ static const NSString* kStateShowsToolba
   aStyle = aStyle | NSTexturedBackgroundWindowMask;
   if ((self = [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag])) {
     mColor = [[TitlebarAndBackgroundColor alloc] initWithWindow:self];
     // Bypass our guard method below.
     [super setBackgroundColor:mColor];
     mBackgroundColor = [NSColor whiteColor];
 
     mUnifiedToolbarHeight = 0.0f;
-    mInUnifiedToolbarReset = NO;
 
     // setBottomCornerRounded: is a private API call, so we check to make sure
     // we respond to it just in case.
     if ([self respondsToSelector:@selector(setBottomCornerRounded:)])
       [self setBottomCornerRounded:NO];
 
     [self setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge];
     [self setContentBorderThickness:0.0f forEdge:NSMaxYEdge];
@@ -2263,30 +2262,16 @@ static const NSString* kStateShowsToolba
   mBackgroundColor = aColor;
 }
 
 - (NSColor*)windowBackgroundColor
 {
   return mBackgroundColor;
 }
 
-// This is called by nsNativeThemeCocoa.mm's RegisterWidgetGeometry.
-// We need to know the toolbar's height in order to draw the correct
-// unified gradient in the titlebar.
-- (void)notifyToolbarAt:(float)aY height:(float)aHeight
-{
-  // Ignore unexpected notifications about the toolbar height
-  if (!mInUnifiedToolbarReset)
-    return;
-
-  if (aY <= 0.0 && aY + aHeight > mUnifiedToolbarHeight) {
-    mUnifiedToolbarHeight = aY + aHeight;
-  }
-}
-
 - (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect
 {
   [self setTitlebarNeedsDisplayInRect:aRect sync:NO];
 }
 
 - (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync
 {
   NSRect titlebarRect = [self titlebarRect];
@@ -2317,37 +2302,30 @@ static const NSString* kStateShowsToolba
 }
 
 - (float)titlebarHeight
 {
   NSRect frameRect = [self frame];
   return frameRect.size.height - [self contentRectForFrameRect:frameRect].size.height;
 }
 
-- (float)beginMaybeResetUnifiedToolbar
-{
-  mInUnifiedToolbarReset = YES;
-  float old = mUnifiedToolbarHeight;
-  mUnifiedToolbarHeight = 0.0;
-  return old;
-}
-
-- (void)endMaybeResetUnifiedToolbar:(float)aOldHeight
+- (void)setUnifiedToolbarHeight:(float)aHeight
 {
-  if (mInUnifiedToolbarReset) {
-    mInUnifiedToolbarReset = NO;
-    if (mUnifiedToolbarHeight == aOldHeight)
-      return;
-
-    [self setContentBorderThickness:mUnifiedToolbarHeight forEdge:NSMaxYEdge];
-
-    // Since this function is only called inside painting, the repaint needs to
-    // be synchronous.
-    [self setTitlebarNeedsDisplayInRect:[self titlebarRect] sync:YES];
-  }
+  if ([self drawsContentsIntoWindowFrame] || aHeight == mUnifiedToolbarHeight)
+    return;
+
+  mUnifiedToolbarHeight = aHeight;
+
+  // Update sheet positioning hint.
+  [self setContentBorderThickness:mUnifiedToolbarHeight forEdge:NSMaxYEdge];
+
+  // Redraw the title bar. If we're inside painting, we'll do it right now,
+  // otherwise we'll just invalidate it.
+  BOOL needSyncRedraw = ([NSView focusView] != nil);
+  [self setTitlebarNeedsDisplayInRect:[self titlebarRect] sync:needSyncRedraw];
 }
 
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState
 {
   BOOL stateChanged = ([self drawsContentsIntoWindowFrame] != aState);
   [super setDrawsContentsIntoWindowFrame:aState];
   if (stateChanged && [[self delegate] isKindOfClass:[WindowDelegate class]]) {
     WindowDelegate *windowDelegate = (WindowDelegate *)[self delegate];
--- a/widget/src/cocoa/nsNativeThemeCocoa.h
+++ b/widget/src/cocoa/nsNativeThemeCocoa.h
@@ -62,19 +62,16 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // The nsITheme interface.
   NS_IMETHOD DrawWidgetBackground(nsIRenderingContext* aContext,
                                   nsIFrame* aFrame,
                                   PRUint8 aWidgetType,
                                   const nsRect& aRect,
                                   const nsRect& aDirtyRect);
-  virtual void RegisterWidgetGeometry(nsIWidget* aWindow,
-                                      PRUint8 aWidgetType,
-                                      const nsIntRect& aRect);
   NS_IMETHOD GetWidgetBorder(nsIDeviceContext* aContext, 
                              nsIFrame* aFrame,
                              PRUint8 aWidgetType,
                              nsIntMargin* aResult);
 
   virtual PRBool GetWidgetPadding(nsIDeviceContext* aContext,
                                   nsIFrame* aFrame,
                                   PRUint8 aWidgetType,
--- a/widget/src/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/src/cocoa/nsNativeThemeCocoa.mm
@@ -1514,35 +1514,16 @@ nsNativeThemeCocoa::DrawResizer(CGContex
   drawInfo.size = kHIThemeGrowBoxSizeNormal;
 
   RenderTransformedHIThemeControl(cgContext, aRect, RenderResizer, &drawInfo,
                                   IsFrameRTL(aFrame));
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
-static PRBool
-IsWindowSpanningToolbar(nsIWidget* aWindow,
-                        PRUint8 aWidgetType,
-                        const nsIntRect& aRect,
-                        ToolbarWindow** aCocoaWindow)
-{
-  nsIWidget* topLevelWidget = aWindow->GetTopLevelWidget();
-  if (!topLevelWidget)
-    return PR_FALSE;
-  NSWindow* win = (NSWindow*)topLevelWidget->GetNativeData(NS_NATIVE_WINDOW);
-  if (!win || ![win isKindOfClass:[ToolbarWindow class]])
-    return PR_FALSE;
-
-  *aCocoaWindow = (ToolbarWindow*)win;
-  return (aWidgetType == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
-          aWidgetType == NS_THEME_TOOLBAR) &&
-         aRect.x == 0 && aRect.width == [win frame].size.width;
-}
-
 NS_IMETHODIMP
 nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame* aFrame,
                                          PRUint8 aWidgetType, const nsRect& aRect,
                                          const nsRect& aDirtyRect)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   // setup to draw into the correct port
@@ -1977,28 +1958,16 @@ nsNativeThemeCocoa::DrawWidgetBackground
 
   nativeDrawing.EndNativeDrawing();
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
-void
-nsNativeThemeCocoa::RegisterWidgetGeometry(nsIWidget* aWindow,
-                                           PRUint8 aWidgetType,
-                                           const nsIntRect& aRect)
-{
-  ToolbarWindow* cocoaWindow;
-  if (IsWindowSpanningToolbar(aWindow, aWidgetType, aRect, &cocoaWindow) &&
-      ![cocoaWindow drawsContentsIntoWindowFrame]) {
-    [cocoaWindow notifyToolbarAt:aRect.y height:aRect.height];
-  }
-}
-                                         
 nsIntMargin
 nsNativeThemeCocoa::RTLAwareMargin(const nsIntMargin& aMargin, nsIFrame* aFrame)
 {
   if (IsFrameRTL(aFrame))
     return nsIntMargin(aMargin.right, aMargin.top, aMargin.left, aMargin.bottom);
 
   return aMargin;
 }
--- a/widget/src/xpwidgets/nsBaseWidget.h
+++ b/widget/src/xpwidgets/nsBaseWidget.h
@@ -114,16 +114,17 @@ public:
   NS_IMETHOD              HideWindowChrome(PRBool aShouldHide);
   NS_IMETHOD              MakeFullScreen(PRBool aFullScreen);
   virtual nsIDeviceContext* GetDeviceContext();
   virtual nsIToolkit*     GetToolkit();
   virtual LayerManager*   GetLayerManager(bool *aAllowRetaining = nsnull);
   virtual LayerManager*   GetLayerManager(LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
                                           bool* aAllowRetaining = nsnull);
   virtual void            DrawOver(LayerManager* aManager, nsIntRect aRect) {}
+  virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
   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();