Backed out 6 changesets (bug 1533562) for breaking reftests and failures in letter-spacing-005.xht
authorNoemi Erli <nerli@mozilla.com>
Fri, 26 Apr 2019 22:26:17 +0300
changeset 530396 d2f707cb83c9ac62fceb976c69d7ce69ca69de06
parent 530395 3432bd434d0f7e2f9c2e911b011a4c1120731ecb
child 530397 e8b8985aa697ef4dad6ed72957186c658669bc1d
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1533562
milestone68.0a1
backs out1976a614f8cec586b331a7d2825d4a370b4fc20b
02adcc70efbe3e0719edcec48c3e282eb964bb5a
00ffda400dc5824428e78eea2a994e02bfb39d75
710d3c0129de293e625a284b450af7024062449d
64720021f45c1fc1b2eaaf78084aa14d99e7b069
68559438c81887217e6c1e1486d1bf1ca0326077
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
Backed out 6 changesets (bug 1533562) for breaking reftests and failures in letter-spacing-005.xht Backed out changeset 1976a614f8ce (bug 1533562) Backed out changeset 02adcc70efbe (bug 1533562) Backed out changeset 00ffda400dc5 (bug 1533562) Backed out changeset 710d3c0129de (bug 1533562) Backed out changeset 64720021f45c (bug 1533562) Backed out changeset 68559438c818 (bug 1533562)
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
widget/cocoa/nsWindowMap.mm
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -596,16 +596,17 @@ class nsChildView final : public nsBaseW
   mozilla::Mutex mViewTearDownLock;
 
   mozilla::Mutex mEffectsLock;
 
   // May be accessed from any thread, protected
   // by mEffectsLock.
   bool mShowsResizeIndicator;
   LayoutDeviceIntRect mResizeIndicatorRect;
+  bool mHasRoundedBottomCorners;
   int mDevPixelCornerRadius;
   bool mIsCoveringTitlebar;
   bool mIsFullscreen;
   bool mIsOpaque;
   LayoutDeviceIntRect mTitlebarRect;
 
   // The area of mTitlebarCGContext that needs to be redrawn during the next
   // transaction. Accessed from any thread, protected by mEffectsLock.
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -181,16 +181,17 @@ static NSMutableDictionary* sNativeKeyEv
                           toGeckoEvent:(WidgetMouseEvent*)outGeckoEvent;
 - (NSMenu*)contextMenu;
 
 - (BOOL)isRectObscuredBySubview:(NSRect)inRect;
 
 - (LayoutDeviceIntRegion)nativeDirtyRegionWithBoundingRect:(NSRect)aRect;
 - (BOOL)isUsingOpenGL;
 
+- (BOOL)hasRoundedBottomCorners;
 - (CGFloat)cornerRadius;
 - (void)clearCorners;
 
 - (void)setGLOpaque:(BOOL)aOpaque;
 
 // Overlay drawing functions for traditional CGContext drawing
 - (void)drawTitleString;
 - (void)maskTopCornersInContext:(CGContextRef)aContext;
@@ -318,16 +319,17 @@ struct SwipeEventQueue {
 nsChildView::nsChildView()
     : nsBaseWidget(),
       mView(nullptr),
       mParentView(nil),
       mParentWidget(nullptr),
       mViewTearDownLock("ChildViewTearDown"),
       mEffectsLock("WidgetEffects"),
       mShowsResizeIndicator(false),
+      mHasRoundedBottomCorners(false),
       mDevPixelCornerRadius{0},
       mIsCoveringTitlebar(false),
       mIsFullscreen(false),
       mIsOpaque(false),
       mTitlebarCGContext(nullptr),
       mBackingScaleFactor(0.0),
       mVisible(false),
       mDrawing(false),
@@ -1734,16 +1736,17 @@ LayoutDeviceIntRect nsChildView::RectCon
 
 void nsChildView::PrepareWindowEffects() {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   bool canBeOpaque;
   {
     MutexAutoLock lock(mEffectsLock);
     mShowsResizeIndicator = ShowsResizeIndicator(&mResizeIndicatorRect);
+    mHasRoundedBottomCorners = [mView hasRoundedBottomCorners];
     CGFloat cornerRadius = [mView cornerRadius];
     mDevPixelCornerRadius = cornerRadius * BackingScaleFactor();
     mIsCoveringTitlebar = [mView isCoveringTitlebar];
     NSInteger styleMask = [[mView window] styleMask];
     bool wasFullscreen = mIsFullscreen;
     nsCocoaWindow* windowWidget = GetXULWindowWidget();
     mIsFullscreen =
         (styleMask & NSFullScreenWindowMask) || (windowWidget && windowWidget->InFullScreenMode());
@@ -2126,17 +2129,17 @@ void nsChildView::MaybeDrawRoundedCorner
   Matrix4x4 flipY = Matrix4x4::Scaling(1, -1, 1);
 
   if (mIsCoveringTitlebar && !mIsFullscreen) {
     // Mask the top corners.
     mCornerMaskImage->Draw(aManager, aRect.TopLeft());
     mCornerMaskImage->Draw(aManager, aRect.TopRight(), flipX);
   }
 
-  if (!mIsFullscreen) {
+  if (mHasRoundedBottomCorners && !mIsFullscreen) {
     // Mask the bottom corners.
     mCornerMaskImage->Draw(aManager, aRect.BottomLeft(), flipY);
     mCornerMaskImage->Draw(aManager, aRect.BottomRight(), flipY * flipX);
   }
 
   // Reset blend mode.
   aManager->gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, LOCAL_GL_ONE,
                                      LOCAL_GL_ONE);
@@ -3334,16 +3337,21 @@ NSEvent* gLastDragMouseDownEvent = nil;
 }
 
 - (BOOL)isUsingOpenGL {
   if (!mGeckoChild || ![self window]) return NO;
 
   return mGLContext || mUsingOMTCompositor;
 }
 
+- (BOOL)hasRoundedBottomCorners {
+  return [[self window] respondsToSelector:@selector(bottomCornerRounded)] &&
+         [[self window] bottomCornerRounded];
+}
+
 - (CGFloat)cornerRadius {
   NSView* frameView = [[[self window] contentView] superview];
   if (!frameView || ![frameView respondsToSelector:@selector(roundedCornerRadius)]) return 4.0f;
   return [frameView roundedCornerRadius];
 }
 
 - (void)setGLOpaque:(BOOL)aOpaque {
   CGLLockContext((CGLContextObj)[mGLContext CGLContextObj]);
@@ -3376,23 +3384,25 @@ NSEvent* gLastDragMouseDownEvent = nil;
   CGFloat w = [self bounds].size.width, h = [self bounds].size.height;
   [[NSColor clearColor] set];
 
   if ([self isCoveringTitlebar]) {
     NSRectFill(NSMakeRect(0, 0, radius, radius));
     NSRectFill(NSMakeRect(w - radius, 0, radius, radius));
   }
 
-  NSRectFill(NSMakeRect(0, h - radius, radius, radius));
-  NSRectFill(NSMakeRect(w - radius, h - radius, radius, radius));
+  if ([self hasRoundedBottomCorners]) {
+    NSRectFill(NSMakeRect(0, h - radius, radius, radius));
+    NSRectFill(NSMakeRect(w - radius, h - radius, radius, radius));
+  }
 }
 
 // This is the analog of nsChildView::MaybeDrawRoundedCorners for CGContexts.
 // We only need to mask the top corners here because Cocoa does the masking
-// for the window's bottom corners automatically.
+// for the window's bottom corners automatically (starting with 10.7).
 - (void)maskTopCornersInContext:(CGContextRef)aContext {
   CGFloat radius = [self cornerRadius];
   int32_t devPixelCornerRadius = mGeckoChild->CocoaPointsToDevPixels(radius);
 
   // First make sure that mTopLeftCornerMask is set up.
   if (!mTopLeftCornerMask || int32_t(CGImageGetWidth(mTopLeftCornerMask)) != devPixelCornerRadius) {
     CGImageRelease(mTopLeftCornerMask);
     CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -54,45 +54,26 @@ typedef struct _nsCocoaWindowList {
   nsTouchBar* mTouchBar;
 }
 
 - (void)importState:(NSDictionary*)aState;
 - (NSMutableDictionary*)exportState;
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
 - (BOOL)drawsContentsIntoWindowFrame;
 
-// These two methods are like contentRectForFrameRect and frameRectForContentRect,
-// but they deal with the rect of the window's "main ChildView" instead of the
-// rect of the window's content view. The two are sometimes sized differently: The
-// window's content view always covers the entire window, whereas the ChildView
-// only covers the full window when drawsContentsIntoWindowFrame is YES. When
-// drawsContentsIntoWindowFrame is NO, there's a titlebar-sized gap above the
-// ChildView within the content view.
-- (NSRect)childViewRectForFrameRect:(NSRect)aFrameRect;
-- (NSRect)frameRectForChildViewRect:(NSRect)aChildViewRect;
-
 - (void)mouseEntered:(NSEvent*)aEvent;
 - (void)mouseExited:(NSEvent*)aEvent;
 - (void)mouseMoved:(NSEvent*)aEvent;
 - (void)updateTrackingArea;
 - (NSView*)trackingAreaView;
 
 - (void)setBeingShown:(BOOL)aValue;
 - (BOOL)isBeingShown;
 - (BOOL)isVisibleOrBeingShown;
 
-// Returns an autoreleased NSArray containing the NSViews that we consider the
-// "contents" of this window. All views in the returned array are subviews of
-// this window's content view. However, the array may not include all of the
-// content view's subviews; concretely, the ToolbarWindow implementation will
-// exclude its TitlebarGradientView from the array that is returned here.
-// In the vast majority of cases, the array will only have a single element:
-// this window's mainChildView.
-- (NSArray<NSView*>*)contentViewContents;
-
 - (ChildView*)mainChildView;
 
 - (NSArray*)titlebarControls;
 
 - (void)setWantsTitleDrawn:(BOOL)aDrawTitle;
 - (BOOL)wantsTitleDrawn;
 
 - (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground;
@@ -113,16 +94,23 @@ typedef struct _nsCocoaWindowList {
 
 // If a window has been explicitly removed from the "window cache" (to
 // deactivate it), it's sometimes necessary to "reset" it to reactivate it
 // (and put it back in the "window cache").  One way to do this, which Apple
 // often uses, is to set the "window number" to '-1' and then back to its
 // original value.
 - (void)_setWindowNumber:(NSInteger)aNumber;
 
+// If we set the window's stylemask to be textured, the corners on the bottom of
+// the window are rounded by default. We use this private method to make
+// the corners square again, a la Safari. Starting with 10.7, all windows have
+// rounded bottom corners, so this call doesn't have any effect there.
+- (void)setBottomCornerRounded:(BOOL)rounded;
+- (BOOL)bottomCornerRounded;
+
 // Present in the same form on OS X since at least OS X 10.5.
 - (NSRect)contentRectForFrameRect:(NSRect)windowFrame styleMask:(NSUInteger)windowStyle;
 - (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle;
 
 // Present since at least OS X 10.5.  The OS calls this method on NSWindow
 // (and its subclasses) to find out which NSFrameView subclass to instantiate
 // to create its "frame view".
 + (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
@@ -164,45 +152,38 @@ typedef struct _nsCocoaWindowList {
 - (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind;
 - (void)windowDidResize:(NSNotification*)aNotification;
 - (nsCocoaWindow*)geckoWidget;
 - (bool)toplevelActiveState;
 - (void)sendToplevelActivateEvents;
 - (void)sendToplevelDeactivateEvents;
 @end
 
-@interface TitlebarGradientView : NSView
-@end
+@class ToolbarWindow;
 
 // NSWindow subclass for handling windows with toolbars.
 @interface ToolbarWindow : BaseWindow {
-  // This window's titlebar gradient view, if present.
-  // Will be nil if drawsContentsIntoWindowFrame is YES.
-  // This view is a subview of the window's content view and gets created and
-  // destroyed by updateTitlebarGradientViewPresence.
-  TitlebarGradientView* mTitlebarGradientView;  // [STRONG]
-
   CGFloat mUnifiedToolbarHeight;
   CGFloat mSheetAttachmentPosition;
   NSRect mWindowButtonsRect;
   NSRect mFullScreenButtonRect;
 }
 - (void)setUnifiedToolbarHeight:(CGFloat)aHeight;
 - (CGFloat)unifiedToolbarHeight;
 - (CGFloat)titlebarHeight;
 - (NSRect)titlebarRect;
-- (void)setTitlebarNeedsDisplay;
+- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync;
+- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect;
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
 - (void)setSheetAttachmentPosition:(CGFloat)aY;
 - (CGFloat)sheetAttachmentPosition;
 - (void)placeWindowButtons:(NSRect)aRect;
 - (void)placeFullScreenButton:(NSRect)aRect;
 - (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition;
 - (NSPoint)fullScreenButtonPositionWithDefaultPosition:(NSPoint)aDefaultPosition;
-- (void)windowMainStateChanged;
 @end
 
 class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa {
  private:
   typedef nsBaseWidget Inherited;
 
  public:
   nsCocoaWindow();
@@ -254,17 +235,16 @@ class nsCocoaWindow final : public nsBas
   void ReleaseFullscreenTransitionAnimation() {
     MOZ_ASSERT(mFullscreenTransitionAnimation, "Should only be called when there is animation");
     [mFullscreenTransitionAnimation release];
     mFullscreenTransitionAnimation = nil;
   }
 
   virtual void Resize(double aWidth, double aHeight, bool aRepaint) override;
   virtual void Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override;
-  NSRect GetClientCocoaRect();
   virtual LayoutDeviceIntRect GetClientBounds() override;
   virtual LayoutDeviceIntRect GetScreenBounds() override;
   void ReportMoveEvent();
   void ReportSizeEvent();
   virtual void SetCursor(nsCursor aDefaultCursor, imgIContainer* aCursorImage, uint32_t aHotspotX,
                          uint32_t aHotspotY) override;
 
   CGFloat BackingScaleFactor();
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -453,17 +453,17 @@ nsresult nsCocoaWindow::CreateNativeWind
   [mWindow setRestorable:NO];
   [mWindow disableSnapshotRestoration];
 
   // setup our notification delegate. Note that setDelegate: does NOT retain.
   mDelegate = [[WindowDelegate alloc] initWithGeckoWindow:this];
   [mWindow setDelegate:mDelegate];
 
   // Make sure that the content rect we gave has been honored.
-  NSRect wantedFrame = [mWindow frameRectForChildViewRect:contentRect];
+  NSRect wantedFrame = [mWindow frameRectForContentRect:contentRect];
   if (!NSEqualRects([mWindow frame], wantedFrame)) {
     // This can happen when the window is not on the primary screen.
     [mWindow setFrame:wantedFrame display:NO];
   }
   UpdateBounds();
 
   if (mWindowType == eWindowType_invisible) {
     [mWindow setLevel:kCGDesktopWindowLevelKey];
@@ -1099,17 +1099,17 @@ void nsCocoaWindow::ConstrainPosition(bo
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 void nsCocoaWindow::SetSizeConstraints(const SizeConstraints& aConstraints) {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   // Popups can be smaller than (60, 60)
   NSRect rect = (mWindowType == eWindowType_popup) ? NSZeroRect : NSMakeRect(0.0, 0.0, 60, 60);
-  rect = [mWindow frameRectForChildViewRect:rect];
+  rect = [mWindow frameRectForContentRect:rect];
 
   CGFloat scaleFactor = BackingScaleFactor();
 
   SizeConstraints c = aConstraints;
   c.mMinSize.width = std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.width, scaleFactor),
                               c.mMinSize.width);
   c.mMinSize.height = std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.height, scaleFactor),
                                c.mMinSize.height);
@@ -1204,39 +1204,36 @@ void nsCocoaWindow::HideWindowChrome(boo
   // Remove child windows.
   NSArray* childWindows = [mWindow childWindows];
   NSEnumerator* enumerator = [childWindows objectEnumerator];
   NSWindow* child = nil;
   while ((child = [enumerator nextObject])) {
     [mWindow removeChildWindow:child];
   }
 
-  // Remove the views in the old window's content view.
-  // The NSArray is autoreleased and retains its NSViews.
-  NSArray<NSView*>* contentViewContents = [mWindow contentViewContents];
-  for (NSView* view in contentViewContents) {
-    [view removeFromSuperviewWithoutNeedingDisplay];
-  }
+  // Remove the content view.
+  NSView* contentView = [mWindow contentView];
+  [contentView retain];
+  [contentView removeFromSuperviewWithoutNeedingDisplay];
 
   // Save state (like window title).
   NSMutableDictionary* state = [mWindow exportState];
 
   // Recreate the window with the right border style.
   NSRect frameRect = [mWindow frame];
   DestroyNativeWindow();
   nsresult rv = CreateNativeWindow(frameRect, aShouldHide ? eBorderStyle_none : mBorderStyle, true);
   NS_ENSURE_SUCCESS_VOID(rv);
 
   // Re-import state.
   [mWindow importState:state];
 
-  // Add the old content view subviews to the new window's content view.
-  for (NSView* view in contentViewContents) {
-    [[mWindow contentView] addSubview:view];
-  }
+  // Reparent the content view.
+  [mWindow setContentView:contentView];
+  [contentView release];
 
   // Reparent child windows.
   enumerator = [childWindows objectEnumerator];
   while ((child = [enumerator nextObject])) {
     [mWindow addChildWindow:child ordered:NSWindowAbove];
   }
 
   // Show the new window.
@@ -1482,32 +1479,33 @@ void nsCocoaWindow::Resize(double aX, do
 }
 
 // Coordinates are desktop pixels
 void nsCocoaWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
   double invScale = 1.0 / BackingScaleFactor();
   DoResize(mBounds.x * invScale, mBounds.y * invScale, aWidth, aHeight, aRepaint, true);
 }
 
-// Return the area that the Gecko ChildView in our window should cover, as an
-// NSRect in screen coordinates (with 0,0 being the bottom left corner of the
-// primary screen).
-NSRect nsCocoaWindow::GetClientCocoaRect() {
-  if (!mWindow) {
-    return NSZeroRect;
-  }
-
-  return [mWindow childViewRectForFrameRect:[mWindow frame]];
-}
-
 LayoutDeviceIntRect nsCocoaWindow::GetClientBounds() {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
   CGFloat scaleFactor = BackingScaleFactor();
-  return nsCocoaUtils::CocoaRectToGeckoRectDevPix(GetClientCocoaRect(), scaleFactor);
+  if (!mWindow) {
+    return nsCocoaUtils::CocoaRectToGeckoRectDevPix(NSZeroRect, scaleFactor);
+  }
+
+  NSRect r;
+  if ([mWindow isKindOfClass:[ToolbarWindow class]] &&
+      [(ToolbarWindow*)mWindow drawsContentsIntoWindowFrame]) {
+    r = [mWindow frame];
+  } else {
+    r = [mWindow contentRectForFrameRect:[mWindow frame]];
+  }
+
+  return nsCocoaUtils::CocoaRectToGeckoRectDevPix(r, scaleFactor);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntRect(0, 0, 0, 0));
 }
 
 void nsCocoaWindow::UpdateBounds() {
   NSRect frame = NSZeroRect;
   if (mWindow) {
     frame = [mWindow frame];
@@ -1853,18 +1851,24 @@ nsresult nsCocoaWindow::SetFocus(bool aS
   }
 
   return NS_OK;
 }
 
 LayoutDeviceIntPoint nsCocoaWindow::WidgetToScreenOffset() {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
-  return nsCocoaUtils::CocoaRectToGeckoRectDevPix(GetClientCocoaRect(), BackingScaleFactor())
-      .TopLeft();
+  NSRect rect = NSZeroRect;
+  LayoutDeviceIntRect r;
+  if (mWindow) {
+    rect = [mWindow contentRectForFrameRect:[mWindow frame]];
+  }
+  r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(rect, BackingScaleFactor());
+
+  return r.TopLeft();
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0, 0));
 }
 
 LayoutDeviceIntPoint nsCocoaWindow::GetClientOffset() {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
   LayoutDeviceIntRect clientRect = GetClientBounds();
@@ -1887,18 +1891,18 @@ LayoutDeviceIntSize nsCocoaWindow::Clien
   // i.e. for windows where [mWindow drawsContentsIntoWindowFrame] is NO.
   //
   // So we call frameRectForContentRect on NSWindow here, instead of mWindow, so
   // that we don't run into our override if this window is a window that draws
   // its content into the titlebar.
   //
   // This is the same thing the windows widget does, but we probably should fix
   // that, see bug 1445738.
-  NSUInteger styleMask = [mWindow styleMask];
-  NSRect inflatedRect = [NSWindow frameRectForContentRect:rect styleMask:styleMask];
+  unsigned int features = [mWindow styleMask];
+  NSRect inflatedRect = [NSWindow frameRectForContentRect:rect styleMask:features];
   r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(inflatedRect, backingScale);
   return r.Size();
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntSize(0, 0));
 }
 
 nsMenuBarX* nsCocoaWindow::GetMenuBar() { return mMenuBar; }
 
@@ -2403,40 +2407,31 @@ already_AddRefed<nsIWidget> nsIWidget::C
   ChildViewMouseTracker::ReEvaluateMouseEnterState();
 
   // [NSApp _isRunningAppModal] will return true if we're running an OS dialog
   // app modally. If one of those is up then we want it to retain its menu bar.
   if ([NSApp _isRunningAppModal]) return;
   NSWindow* window = [aNotification object];
   if (window) [WindowDelegate paintMenubarForWindow:window];
 
-  if ([window isKindOfClass:[ToolbarWindow class]]) {
-    [(ToolbarWindow*)window windowMainStateChanged];
-  }
-
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 - (void)windowDidResignMain:(NSNotification*)aNotification {
   RollUpPopups();
   ChildViewMouseTracker::ReEvaluateMouseEnterState();
 
   // [NSApp _isRunningAppModal] will return true if we're running an OS dialog
   // app modally. If one of those is up then we want it to retain its menu bar.
   if ([NSApp _isRunningAppModal]) return;
   RefPtr<nsMenuBarX> hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar();
   if (hiddenWindowMenuBar) {
     // printf("painting hidden window menu bar due to window losing main status\n");
     hiddenWindowMenuBar->Paint();
   }
-
-  NSWindow* window = [aNotification object];
-  if ([window isKindOfClass:[ToolbarWindow class]]) {
-    [(ToolbarWindow*)window windowMainStateChanged];
-  }
 }
 
 - (void)windowDidBecomeKey:(NSNotification*)aNotification {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   RollUpPopups();
   ChildViewMouseTracker::ReEvaluateMouseEnterState();
 
@@ -2585,16 +2580,17 @@ already_AddRefed<nsIWidget> nsIWidget::C
 }
 
 @end
 
 @interface NSView (FrameViewMethodSwizzling)
 - (NSPoint)FrameView__closeButtonOrigin;
 - (NSPoint)FrameView__fullScreenButtonOrigin;
 - (BOOL)FrameView__wantsFloatingTitlebar;
+- (NSRect)FrameView__unifiedToolbarFrame;
 @end
 
 @implementation NSView (FrameViewMethodSwizzling)
 
 - (NSPoint)FrameView__closeButtonOrigin {
   NSPoint defaultPosition = [self FrameView__closeButtonOrigin];
   if ([[self window] isKindOfClass:[ToolbarWindow class]]) {
     return [(ToolbarWindow*)[self window] windowButtonsPositionWithDefaultPosition:defaultPosition];
@@ -2610,16 +2606,28 @@ already_AddRefed<nsIWidget> nsIWidget::C
   }
   return defaultPosition;
 }
 
 - (BOOL)FrameView__wantsFloatingTitlebar {
   return NO;
 }
 
+- (NSRect)FrameView__unifiedToolbarFrame {
+  NSRect defaultFrame = [self FrameView__unifiedToolbarFrame];
+  if ([[self window] isKindOfClass:[ToolbarWindow class]]) {
+    CGFloat unifiedToolbarHeight = [(ToolbarWindow*)[self window] unifiedToolbarHeight];
+    CGFloat topEdge = NSMaxY(defaultFrame);
+    CGFloat bottomEdge = topEdge - unifiedToolbarHeight;
+    return NSMakeRect(defaultFrame.origin.x, bottomEdge, defaultFrame.size.width,
+                      unifiedToolbarHeight);
+  }
+  return defaultFrame;
+}
+
 @end
 
 static NSMutableSet* gSwizzledFrameViewClasses = nil;
 
 @interface NSWindow (PrivateSetNeedsDisplayInRectMethod)
 - (void)_setNeedsDisplayInRect:(NSRect)aRect;
 @end
 
@@ -2658,16 +2666,17 @@ static NSMutableSet* gSwizzledFrameViewC
 
 @interface NSView (NSVisualEffectViewSetMaskImage)
 - (void)setMaskImage:(NSImage*)image;
 @end
 
 @interface BaseWindow (Private)
 - (void)removeTrackingArea;
 - (void)cursorUpdated:(NSEvent*)aEvent;
+- (void)updateContentViewSize;
 - (void)reflowTitlebarElements;
 @end
 
 @implementation BaseWindow
 
 // The frame of a window is implemented using undocumented NSView subclasses.
 // We offset the window buttons by overriding the methods _closeButtonOrigin
 // and _fullScreenButtonOrigin on these frame view classes. The class which is
@@ -2688,16 +2697,18 @@ static NSMutableSet* gSwizzledFrameViewC
   }
 
   static IMP our_closeButtonOrigin =
       class_getMethodImplementation([NSView class], @selector(FrameView__closeButtonOrigin));
   static IMP our_fullScreenButtonOrigin =
       class_getMethodImplementation([NSView class], @selector(FrameView__fullScreenButtonOrigin));
   static IMP our_wantsFloatingTitlebar =
       class_getMethodImplementation([NSView class], @selector(FrameView__wantsFloatingTitlebar));
+  static IMP our_unifiedToolbarFrame =
+      class_getMethodImplementation([NSView class], @selector(FrameView__unifiedToolbarFrame));
 
   if (![gSwizzledFrameViewClasses containsObject:frameViewClass]) {
     // Either of these methods might be implemented in both a subclass of
     // NSFrameView and one of its own subclasses.  Which means that if we
     // aren't careful we might end up swizzling the same method twice.
     // Since method swizzling involves swapping pointers, this would break
     // things.
     IMP _closeButtonOrigin =
@@ -2713,16 +2724,22 @@ static NSMutableSet* gSwizzledFrameViewC
                                 @selector(FrameView__fullScreenButtonOrigin));
     }
     IMP _wantsFloatingTitlebar =
         class_getMethodImplementation(frameViewClass, @selector(_wantsFloatingTitlebar));
     if (_wantsFloatingTitlebar && _wantsFloatingTitlebar != our_wantsFloatingTitlebar) {
       nsToolkit::SwizzleMethods(frameViewClass, @selector(_wantsFloatingTitlebar),
                                 @selector(FrameView__wantsFloatingTitlebar));
     }
+    IMP _unifiedToolbarFrame =
+        class_getMethodImplementation(frameViewClass, @selector(_unifiedToolbarFrame));
+    if (_unifiedToolbarFrame && _unifiedToolbarFrame != our_unifiedToolbarFrame) {
+      nsToolkit::SwizzleMethods(frameViewClass, @selector(_unifiedToolbarFrame),
+                                @selector(FrameView__unifiedToolbarFrame));
+    }
     [gSwizzledFrameViewClasses addObject:frameViewClass];
   }
 
   return frameViewClass;
 }
 
 - (id)initWithContentRect:(NSRect)aContentRect
                 styleMask:(NSUInteger)aStyle
@@ -2855,40 +2872,28 @@ static const NSString* kStateCollectionB
             forKey:kStateCollectionBehavior];
   return state;
 }
 
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState {
   bool changed = (aState != mDrawsIntoWindowFrame);
   mDrawsIntoWindowFrame = aState;
   if (changed) {
+    [self updateContentViewSize];
     [self reflowTitlebarElements];
+    if ([self respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {
+      [self setTitlebarAppearsTransparent:mDrawsIntoWindowFrame];
+    }
   }
 }
 
 - (BOOL)drawsContentsIntoWindowFrame {
   return mDrawsIntoWindowFrame;
 }
 
-- (NSRect)childViewRectForFrameRect:(NSRect)aFrameRect {
-  if (mDrawsIntoWindowFrame) {
-    return aFrameRect;
-  }
-  NSUInteger styleMask = [self styleMask];
-  return [NSWindow contentRectForFrameRect:aFrameRect styleMask:styleMask];
-}
-
-- (NSRect)frameRectForChildViewRect:(NSRect)aChildViewRect {
-  if (mDrawsIntoWindowFrame) {
-    return aChildViewRect;
-  }
-  NSUInteger styleMask = [self styleMask];
-  return [NSWindow frameRectForContentRect:aChildViewRect styleMask:styleMask];
-}
-
 - (void)setWantsTitleDrawn:(BOOL)aDrawTitle {
   mDrawTitle = aDrawTitle;
   if ([self respondsToSelector:@selector(setTitleVisibility:)]) {
     [self setTitleVisibility:mDrawTitle ? NSWindowTitleVisible : NSWindowTitleHidden];
   }
 }
 
 - (BOOL)wantsTitleDrawn {
@@ -2904,20 +2909,16 @@ static const NSString* kStateCollectionB
   return mBrightTitlebarForeground;
 }
 
 - (NSView*)trackingAreaView {
   NSView* contentView = [self contentView];
   return [contentView superview] ? [contentView superview] : contentView;
 }
 
-- (NSArray<NSView*>*)contentViewContents {
-  return [[[[self contentView] subviews] copy] autorelease];
-}
-
 - (ChildView*)mainChildView {
   NSView* contentView = [self contentView];
   NSView* lastView = [[contentView subviews] lastObject];
   if ([lastView isKindOfClass:[ChildView class]]) {
     return (ChildView*)lastView;
   }
   return nil;
 }
@@ -2971,39 +2972,68 @@ static const NSString* kStateCollectionB
 }
 
 - (NSRect)getAndResetNativeDirtyRect {
   NSRect dirtyRect = mDirtyRect;
   mDirtyRect = NSZeroRect;
   return dirtyRect;
 }
 
+- (void)updateContentViewSize {
+  NSRect rect = [self contentRectForFrameRect:[self frame]];
+  [[self contentView] setFrameSize:rect.size];
+}
+
 // Possibly move the titlebar buttons.
 - (void)reflowTitlebarElements {
   NSView* frameView = [[self contentView] superview];
   if ([frameView respondsToSelector:@selector(_tileTitlebarAndRedisplay:)]) {
     [frameView _tileTitlebarAndRedisplay:NO];
   }
 }
 
 // Override methods that translate between content rect and frame rect.
 - (NSRect)contentRectForFrameRect:(NSRect)aRect {
-  return aRect;
+  if ([self drawsContentsIntoWindowFrame]) {
+    return aRect;
+  }
+  return [super contentRectForFrameRect:aRect];
 }
 
 - (NSRect)contentRectForFrameRect:(NSRect)aRect styleMask:(NSUInteger)aMask {
-  return aRect;
+  if ([self drawsContentsIntoWindowFrame]) {
+    return aRect;
+  }
+  // Call the instance method on super, if it exists (it's undocumented so we
+  // shouldn't rely on it), or fall back to the (documented) class method.
+  if ([NSWindow instancesRespondToSelector:@selector(contentRectForFrameRect:styleMask:)]) {
+    return [super contentRectForFrameRect:aRect styleMask:aMask];
+  } else {
+    return [NSWindow contentRectForFrameRect:aRect styleMask:aMask];
+  }
 }
 
 - (NSRect)frameRectForContentRect:(NSRect)aRect {
-  return aRect;
+  if ([self drawsContentsIntoWindowFrame]) {
+    return aRect;
+  }
+  return [super frameRectForContentRect:aRect];
 }
 
 - (NSRect)frameRectForContentRect:(NSRect)aRect styleMask:(NSUInteger)aMask {
-  return aRect;
+  if ([self drawsContentsIntoWindowFrame]) {
+    return aRect;
+  }
+  // Call the instance method on super, if it exists (it's undocumented so we
+  // shouldn't rely on it), or fall back to the (documented) class method.
+  if ([NSWindow instancesRespondToSelector:@selector(frameRectForContentRect:styleMask:)]) {
+    return [super frameRectForContentRect:aRect styleMask:aMask];
+  } else {
+    return [NSWindow frameRectForContentRect:aRect styleMask:aMask];
+  }
 }
 
 - (void)setContentView:(NSView*)aView {
   [super setContentView:aView];
 
   // Now move the contentView to the bottommost layer so that it's guaranteed
   // to be under the window buttons.
   NSView* frameView = [aView superview];
@@ -3092,205 +3122,121 @@ static const NSString* kStateCollectionB
 }
 
 - (void)releaseJSObjects {
   [mTouchBar releaseJSObjects];
 }
 
 @end
 
-@interface NSView (NSThemeFrame)
-- (void)_drawTitleStringInClip:(NSRect)aRect;
-- (void)_maskCorners:(NSUInteger)aFlags clipRect:(NSRect)aRect;
-@end
-
-@implementation TitlebarGradientView
-
-- (void)drawRect:(NSRect)aRect {
-  CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-  ToolbarWindow* window = (ToolbarWindow*)[self window];
-  nsNativeThemeCocoa::DrawNativeTitlebar(ctx, NSRectToCGRect([self bounds]),
-                                         [window unifiedToolbarHeight], [window isMainWindow], NO);
-
-  // The following is only necessary because we're not using
-  // NSFullSizeContentViewWindowMask yet: We need to mask our drawing to the
-  // rounded top corners of the window, and we need to draw the title string
-  // on top. That's because the title string is drawn as part of the frame view
-  // and this view covers that drawing up.
-  // Once we use NSFullSizeContentViewWindowMask and remove our override of
-  // _wantsFloatingTitlebar, Cocoa will draw the title string as part of a
-  // separate view which sits on top of the window's content view, and we'll be
-  // able to remove the code below.
-
-  NSView* frameView = [[[self window] contentView] superview];
-  if (!frameView || ![frameView respondsToSelector:@selector(_maskCorners:clipRect:)] ||
-      ![frameView respondsToSelector:@selector(_drawTitleStringInClip:)]) {
-    return;
-  }
-
-  NSPoint offsetToFrameView = [self convertPoint:NSZeroPoint toView:frameView];
-  NSRect clipRect = {offsetToFrameView, [self bounds].size};
-
-  // Both this view and frameView return NO from isFlipped. Switch into
-  // frameView's coordinate system using a translation by the offset.
-  CGContextSaveGState(ctx);
-  CGContextTranslateCTM(ctx, -offsetToFrameView.x, -offsetToFrameView.y);
-
-  [frameView _maskCorners:2 clipRect:clipRect];
-  [frameView _drawTitleStringInClip:clipRect];
-
-  CGContextRestoreGState(ctx);
-}
-
-- (BOOL)isOpaque {
-  return YES;
-}
-
-- (NSView*)hitTest:(NSPoint)aPoint {
-  return nil;
-}
-
-@end
-
-// This class allows us to exercise control over the window's title bar. It is
-// used for all windows with titlebars.
+// This class allows us to exercise control over the window's title bar. This
+// allows for a "unified toolbar" look without having to extend the content
+// area into the title bar.
 //
-// ToolbarWindow supports two modes:
-//  - drawsContentsIntoWindowFrame mode: In this mode, the Gecko ChildView is
-//    sized to cover the entire window frame and manages titlebar drawing.
-//  - separate titlebar mode, with support for unified toolbars: In this mode,
-//    the Gecko ChildView does not extend into the titlebar. However, this
-//    window's content view (which is the ChildView's superview) *does* extend
-//    into the titlebar. Moreover, in this mode, we place a TitlebarGradientView
-//    in the content view, as a sibling of the ChildView.
-//
-// The "separate titlebar mode" supports the "unified toolbar" look:
-// If there's a toolbar right below the titlebar, the two can "connect" and
-// form a single gradient without a separator line in between.
-//
-// The following mechanism communicates the height of the unified toolbar to
-// the ToolbarWindow:
-//
+// 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 toolbar.
 // 2) When the toolbar is visible and we paint the application chrome
 //    window, the array that Gecko passes nsChildView::UpdateThemeGeometries
 //    will contain an entry for the widget type StyleAppearance::Toolbar.
-// 3) nsChildView::UpdateThemeGeometries passes the toolbar's height, plus the
-//    titlebar height, to -[ToolbarWindow setUnifiedToolbarHeight:].
+// 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.
 //
-// The actual drawing of the gradient happens in two parts: The titlebar part
-// (i.e. the top 22 pixels of the gradient) is drawn by the TitlebarGradientView,
-// which is a subview of the window's content view and a sibling of the ChildView.
-// The rest of the gradient is drawn by Gecko into the ChildView, as part of the
-// -moz-appearance rendering of the toolbar.
+// 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. 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.
+//
+// Note that in drawsContentsIntoWindowFrame mode, titlebar drawing works in a
+// completely different way: In that mode, the window's mainChildView will
+// cover the titlebar completely and nothing that happens in the window
+// background will reach the screen.
 @implementation ToolbarWindow
 
-- (id)initWithContentRect:(NSRect)aChildViewRect
+- (id)initWithContentRect:(NSRect)aContentRect
                 styleMask:(NSUInteger)aStyle
                   backing:(NSBackingStoreType)aBufferingType
                     defer:(BOOL)aFlag {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
-  // We treat aChildViewRect as the rectangle that the window's main ChildView
-  // should be sized to. Get the right frameRect for the requested child view
-  // rect.
-  NSRect frameRect = [NSWindow frameRectForContentRect:aChildViewRect styleMask:aStyle];
-
-  // -[NSWindow initWithContentRect:styleMask:backing:defer:] calls
-  // [self frameRectForContentRect:styleMask:] to convert the supplied content
-  // rect to the window's frame rect. We've overridden that method to be a
-  // pass-through function. So, in order to get the intended frameRect, we need
-  // to supply frameRect itself as the "content rect".
-  NSRect contentRect = frameRect;
-
-  if ((self = [super initWithContentRect:contentRect
+  if ((self = [super initWithContentRect:aContentRect
                                styleMask:aStyle
                                  backing:aBufferingType
                                    defer:aFlag])) {
-    mTitlebarGradientView = nil;
     mUnifiedToolbarHeight = 22.0f;
-    mSheetAttachmentPosition = aChildViewRect.size.height;
+    mSheetAttachmentPosition = aContentRect.size.height;
     mWindowButtonsRect = NSZeroRect;
     mFullScreenButtonRect = NSZeroRect;
 
-    if ([self respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {
-      [self setTitlebarAppearsTransparent:YES];
-    }
-
-    [self updateTitlebarGradientViewPresence];
+    // 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:YES];
   }
   return self;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
-- (void)dealloc {
-  [mTitlebarGradientView release];
-  [super dealloc];
-}
-
-- (NSArray<NSView*>*)contentViewContents {
-  NSMutableArray<NSView*>* contents = [[[self contentView] subviews] mutableCopy];
-  if (mTitlebarGradientView) {
-    // Do not include the titlebar gradient view in the returned array.
-    [contents removeObject:mTitlebarGradientView];
-  }
-  return [contents autorelease];
+- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect {
+  [self setTitlebarNeedsDisplayInRect:aRect sync:NO];
 }
 
-- (void)updateTitlebarGradientViewPresence {
-  BOOL needTitlebarView = ![self drawsContentsIntoWindowFrame];
-  if (needTitlebarView && !mTitlebarGradientView) {
-    mTitlebarGradientView = [[TitlebarGradientView alloc] initWithFrame:[self titlebarRect]];
-    mTitlebarGradientView.autoresizingMask = NSViewWidthSizable | NSViewMinYMargin;
-    [self.contentView addSubview:mTitlebarGradientView];
-  } else if (!needTitlebarView && mTitlebarGradientView) {
-    [mTitlebarGradientView removeFromSuperview];
-    [mTitlebarGradientView release];
-    mTitlebarGradientView = nil;
+- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync {
+  NSRect titlebarRect = [self titlebarRect];
+  NSRect rect = NSIntersectionRect(titlebarRect, aRect);
+  if (NSIsEmptyRect(rect)) return;
+
+  NSView* borderView = [[self contentView] superview];
+  if (!borderView) return;
+
+  if (aSync) {
+    [borderView displayRect:rect];
+  } else {
+    [borderView setNeedsDisplayInRect:rect];
   }
 }
 
-- (void)windowMainStateChanged {
-  [self setTitlebarNeedsDisplay];
-}
-
-- (void)setTitlebarNeedsDisplay {
-  [mTitlebarGradientView setNeedsDisplay:YES];
-}
-
 - (NSRect)titlebarRect {
   CGFloat titlebarHeight = [self titlebarHeight];
   return NSMakeRect(0, [self frame].size.height - titlebarHeight, [self frame].size.width,
                     titlebarHeight);
 }
 
 // Returns the unified height of titlebar + toolbar.
 - (CGFloat)unifiedToolbarHeight {
   return mUnifiedToolbarHeight;
 }
 
 - (CGFloat)titlebarHeight {
   // We use the original content rect here, not what we return from
   // [self contentRectForFrameRect:], because that would give us a
-  // titlebarHeight of zero.
+  // titlebarHeight of zero in drawsContentsIntoWindowFrame mode.
   NSRect frameRect = [self frame];
-  NSUInteger styleMask = [self styleMask];
-  NSRect originalContentRect = [NSWindow contentRectForFrameRect:frameRect styleMask:styleMask];
+  NSRect originalContentRect = [NSWindow contentRectForFrameRect:frameRect
+                                                       styleMask:[self styleMask]];
   return NSMaxY(frameRect) - NSMaxY(originalContentRect);
 }
 
 // Stores the complete height of titlebar + toolbar.
 - (void)setUnifiedToolbarHeight:(CGFloat)aHeight {
   if (aHeight == mUnifiedToolbarHeight) return;
 
   mUnifiedToolbarHeight = aHeight;
 
   if (![self drawsContentsIntoWindowFrame]) {
-    [self setTitlebarNeedsDisplay];
+    // 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];
   }
 }
 
 // Extending the content area into the title bar works by resizing the
 // mainChildView so that it covers the titlebar.
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState {
   BOOL stateChanged = ([self drawsContentsIntoWindowFrame] != aState);
   [super setDrawsContentsIntoWindowFrame:aState];
@@ -3308,23 +3254,21 @@ static const NSString* kStateCollectionB
 
     // Resizing the content area causes a reflow which would send a synthesized
     // mousemove event to the old mouse position relative to the top left
     // corner of the content area. But the mouse has shifted relative to the
     // content area, so that event would have wrong position information. So
     // we'll send a mouse move event with the correct new position.
     ChildViewMouseTracker::ResendLastMouseMoveEvent();
   }
-
-  [self updateTitlebarGradientViewPresence];
 }
 
 - (void)setWantsTitleDrawn:(BOOL)aDrawTitle {
   [super setWantsTitleDrawn:aDrawTitle];
-  [self setTitlebarNeedsDisplay];
+  [self setTitlebarNeedsDisplayInRect:[self titlebarRect]];
 }
 
 - (void)setSheetAttachmentPosition:(CGFloat)aY {
   mSheetAttachmentPosition = aY;
 }
 
 - (CGFloat)sheetAttachmentPosition {
   return mSheetAttachmentPosition;
--- a/widget/cocoa/nsWindowMap.mm
+++ b/widget/cocoa/nsWindowMap.mm
@@ -225,27 +225,31 @@
   NSWindow* window = (NSWindow*)[inNotification object];
 
   id delegate = [window delegate];
   if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) {
     [TopLevelWindowData activateInWindowViews:window];
   } else if ([window isSheet]) {
     [TopLevelWindowData activateInWindow:window];
   }
+
+  [[window contentView] setNeedsDisplay:YES];
 }
 
 - (void)windowResignedKey:(NSNotification*)inNotification {
   NSWindow* window = (NSWindow*)[inNotification object];
 
   id delegate = [window delegate];
   if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) {
     [TopLevelWindowData deactivateInWindowViews:window];
   } else if ([window isSheet]) {
     [TopLevelWindowData deactivateInWindow:window];
   }
+
+  [[window contentView] setNeedsDisplay:YES];
 }
 
 // The appearance of a top-level window depends on its main state (not its key
 // state).  So (for non-embedders) we need to ensure that a top-level window
 // is main when an NS_ACTIVATE event is sent to Gecko for it.
 - (void)windowBecameMain:(NSNotification*)inNotification {
   NSWindow* window = (NSWindow*)[inNotification object];