Bug 1533562 - Always make the content view of ToolbarWindows cover the entire window. r=spohl
☠☠ backed out by 73e8dcb8be07 ☠ ☠
authorMarkus Stange <mstange@themasta.com>
Mon, 22 Apr 2019 19:26:38 +0000
changeset 470393 498cd34eea782ce73c1eaffd193427add877117c
parent 470392 3a3b4d52e10a17f947717e0e468665d2bdcfb57e
child 470394 8970cdb3c04a11ddbe86c53d5e759685949a0cb3
push id35905
push userdvarga@mozilla.com
push dateTue, 23 Apr 2019 09:53:27 +0000
treeherdermozilla-central@831918f009f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersspohl
bugs1533562
milestone68.0a1
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 1533562 - Always make the content view of ToolbarWindows cover the entire window. r=spohl Differential Revision: https://phabricator.services.mozilla.com/D22645
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -54,16 +54,25 @@ typedef struct _nsCocoaWindowList {
   nsTouchBar* mTouchBar;
 }
 
 - (void)importState:(NSDictionary*)aState;
 - (NSMutableDictionary*)exportState;
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
 - (BOOL)drawsContentsIntoWindowFrame;
 
+// Two methods akin to contentRectForFrameRect and frameRectForContentRect,
+// which convert between the window's frame rect and the rect that our Gecko
+// ChildView would occupy. This is different because we make the window's
+// content view always cover the entire window; when drawsContentsIntoWindowFrame
+// is NO, the content view is larger than the ChildView because it includes the
+// titlebar whereas the ChildView does not.
+- (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;
@@ -227,16 +236,17 @@ 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 frameRectForContentRect:contentRect];
+  NSRect wantedFrame = [mWindow frameRectForChildViewRect: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 frameRectForContentRect:rect];
+  rect = [mWindow frameRectForChildViewRect: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);
@@ -1479,33 +1479,32 @@ 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();
-  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);
+  return nsCocoaUtils::CocoaRectToGeckoRectDevPix(GetClientCocoaRect(), scaleFactor);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntRect(0, 0, 0, 0));
 }
 
 void nsCocoaWindow::UpdateBounds() {
   NSRect frame = NSZeroRect;
   if (mWindow) {
     frame = [mWindow frame];
@@ -1851,24 +1850,18 @@ nsresult nsCocoaWindow::SetFocus(bool aS
   }
 
   return NS_OK;
 }
 
 LayoutDeviceIntPoint nsCocoaWindow::WidgetToScreenOffset() {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
-  NSRect rect = NSZeroRect;
-  LayoutDeviceIntRect r;
-  if (mWindow) {
-    rect = [mWindow contentRectForFrameRect:[mWindow frame]];
-  }
-  r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(rect, BackingScaleFactor());
-
-  return r.TopLeft();
+  return nsCocoaUtils::CocoaRectToGeckoRectDevPix(GetClientCocoaRect(), BackingScaleFactor())
+      .TopLeft();
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0, 0));
 }
 
 LayoutDeviceIntPoint nsCocoaWindow::GetClientOffset() {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
   LayoutDeviceIntRect clientRect = GetClientBounds();
@@ -1891,18 +1884,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.
-  unsigned int features = [mWindow styleMask];
-  NSRect inflatedRect = [NSWindow frameRectForContentRect:rect styleMask:features];
+  NSUInteger styleMask = [mWindow styleMask];
+  NSRect inflatedRect = [NSWindow frameRectForContentRect:rect styleMask:styleMask];
   r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(inflatedRect, backingScale);
   return r.Size();
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntSize(0, 0));
 }
 
 nsMenuBarX* nsCocoaWindow::GetMenuBar() { return mMenuBar; }
 
@@ -2653,17 +2646,16 @@ 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
@@ -2851,28 +2843,43 @@ 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 {
@@ -2951,68 +2958,39 @@ 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 {
-  if ([self drawsContentsIntoWindowFrame]) {
-    return aRect;
-  }
-  return [super contentRectForFrameRect:aRect];
+  return aRect;
 }
 
 - (NSRect)contentRectForFrameRect:(NSRect)aRect styleMask:(NSUInteger)aMask {
-  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];
-  }
+  return aRect;
 }
 
 - (NSRect)frameRectForContentRect:(NSRect)aRect {
-  if ([self drawsContentsIntoWindowFrame]) {
-    return aRect;
-  }
-  return [super frameRectForContentRect:aRect];
+  return aRect;
 }
 
 - (NSRect)frameRectForContentRect:(NSRect)aRect styleMask:(NSUInteger)aMask {
-  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];
-  }
+  return aRect;
 }
 
 - (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];
@@ -3174,20 +3152,20 @@ static const NSString* kStateCollectionB
 // 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 in drawsContentsIntoWindowFrame mode.
+  // titlebarHeight of zero.
   NSRect frameRect = [self frame];
-  NSRect originalContentRect = [NSWindow contentRectForFrameRect:frameRect
-                                                       styleMask:[self styleMask]];
+  NSUInteger styleMask = [self styleMask];
+  NSRect originalContentRect = [NSWindow contentRectForFrameRect:frameRect styleMask:styleMask];
   return NSMaxY(frameRect) - NSMaxY(originalContentRect);
 }
 
 // Stores the complete height of titlebar + toolbar.
 - (void)setUnifiedToolbarHeight:(CGFloat)aHeight {
   if (aHeight == mUnifiedToolbarHeight) return;
 
   mUnifiedToolbarHeight = aHeight;